@datadog/datadog-ci 0.17.9 → 0.17.13

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.
Files changed (81) hide show
  1. package/LICENSE-3rdparty.csv +2 -0
  2. package/README.md +9 -2
  3. package/dist/{commands/dependencies/index.d.ts → cli.d.ts} +0 -0
  4. package/dist/cli.js +34 -0
  5. package/dist/commands/{dsyms/index.d.ts → dependencies/cli.d.ts} +0 -0
  6. package/dist/commands/dependencies/{index.js → cli.js} +0 -0
  7. package/dist/commands/dependencies/upload.d.ts +1 -1
  8. package/dist/commands/{git-metadata/index.d.ts → dsyms/cli.d.ts} +0 -0
  9. package/dist/commands/dsyms/{index.js → cli.js} +0 -0
  10. package/dist/commands/dsyms/upload.d.ts +1 -1
  11. package/dist/commands/{junit/index.d.ts → git-metadata/cli.d.ts} +0 -0
  12. package/dist/commands/git-metadata/{index.js → cli.js} +0 -0
  13. package/dist/commands/git-metadata/upload.d.ts +1 -1
  14. package/dist/commands/git-metadata/upload.js +6 -1
  15. package/dist/commands/{lambda/index.d.ts → junit/cli.d.ts} +0 -0
  16. package/dist/commands/junit/{index.js → cli.js} +0 -0
  17. package/dist/commands/junit/upload.d.ts +1 -1
  18. package/dist/commands/junit/upload.js +1 -1
  19. package/dist/commands/lambda/__tests__/fixtures.d.ts +5 -1
  20. package/dist/commands/lambda/__tests__/fixtures.js +13 -2
  21. package/dist/commands/lambda/__tests__/functions/commons.test.js +400 -0
  22. package/dist/commands/lambda/__tests__/functions/instrument.test.js +229 -117
  23. package/dist/commands/lambda/__tests__/functions/uninstrument.test.js +80 -7
  24. package/dist/commands/lambda/__tests__/instrument.test.js +542 -111
  25. package/dist/commands/{sourcemaps/index.d.ts → lambda/__tests__/prompt.test.d.ts} +0 -0
  26. package/dist/commands/lambda/__tests__/prompt.test.js +216 -0
  27. package/dist/commands/lambda/__tests__/uninstrument.test.js +381 -17
  28. package/dist/commands/{trace/index.d.ts → lambda/cli.d.ts} +0 -0
  29. package/dist/commands/lambda/{index.js → cli.js} +0 -0
  30. package/dist/commands/lambda/constants.d.ts +27 -6
  31. package/dist/commands/lambda/constants.js +63 -6
  32. package/dist/commands/lambda/functions/commons.d.ts +49 -4
  33. package/dist/commands/lambda/functions/commons.js +198 -7
  34. package/dist/commands/lambda/functions/instrument.d.ts +5 -14
  35. package/dist/commands/lambda/functions/instrument.js +63 -80
  36. package/dist/commands/lambda/functions/uninstrument.d.ts +3 -2
  37. package/dist/commands/lambda/functions/uninstrument.js +23 -11
  38. package/dist/commands/lambda/instrument.d.ts +2 -1
  39. package/dist/commands/lambda/instrument.js +112 -58
  40. package/dist/commands/lambda/interfaces.d.ts +4 -1
  41. package/dist/commands/lambda/loggroup.js +3 -1
  42. package/dist/commands/lambda/prompt.d.ts +9 -0
  43. package/dist/commands/lambda/prompt.js +187 -0
  44. package/dist/commands/lambda/uninstrument.d.ts +2 -0
  45. package/dist/commands/lambda/uninstrument.js +107 -30
  46. package/dist/commands/sourcemaps/cli.d.ts +1 -0
  47. package/dist/commands/sourcemaps/{index.js → cli.js} +0 -0
  48. package/dist/commands/sourcemaps/upload.d.ts +1 -1
  49. package/dist/commands/synthetics/__tests__/cli.test.js +36 -13
  50. package/dist/commands/synthetics/__tests__/fixtures.js +1 -0
  51. package/dist/commands/synthetics/__tests__/run-test.test.js +48 -2
  52. package/dist/commands/synthetics/__tests__/utils.test.js +11 -4
  53. package/dist/commands/synthetics/__tests__/websocket.test.js +3 -3
  54. package/dist/commands/synthetics/cli.d.ts +1 -26
  55. package/dist/commands/synthetics/cli.js +2 -227
  56. package/dist/commands/synthetics/command.d.ts +27 -0
  57. package/dist/commands/synthetics/command.js +236 -0
  58. package/dist/commands/synthetics/index.d.ts +5 -1
  59. package/dist/commands/synthetics/index.js +31 -2
  60. package/dist/commands/synthetics/interfaces.d.ts +8 -3
  61. package/dist/commands/synthetics/interfaces.js +7 -3
  62. package/dist/commands/synthetics/reporters/default.js +5 -1
  63. package/dist/commands/synthetics/run-test.js +3 -1
  64. package/dist/commands/synthetics/utils.d.ts +3 -3
  65. package/dist/commands/synthetics/utils.js +17 -8
  66. package/dist/commands/trace/api.js +1 -1
  67. package/dist/commands/trace/cli.d.ts +1 -0
  68. package/dist/commands/trace/{index.js → cli.js} +0 -0
  69. package/dist/commands/trace/trace.d.ts +1 -1
  70. package/dist/helpers/__tests__/ci.test.js +97 -136
  71. package/dist/helpers/__tests__/user-provided-git.test.js +81 -27
  72. package/dist/helpers/__tests__/utils.test.js +4 -0
  73. package/dist/helpers/ci.js +54 -95
  74. package/dist/helpers/interfaces.d.ts +28 -2
  75. package/dist/helpers/user-provided-git.d.ts +2 -1
  76. package/dist/helpers/user-provided-git.js +29 -5
  77. package/dist/helpers/utils.d.ts +4 -0
  78. package/dist/helpers/utils.js +18 -1
  79. package/dist/index.d.ts +3 -1
  80. package/dist/index.js +23 -31
  81. package/package.json +10 -8
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ jest.mock('inquirer');
13
+ const chalk_1 = require("chalk");
14
+ const inquirer_1 = require("inquirer");
15
+ const constants_1 = require("../constants");
16
+ const prompt_1 = require("../prompt");
17
+ const fixtures_1 = require("./fixtures");
18
+ describe('prompt', () => {
19
+ describe('confirmationQuestion', () => {
20
+ test('returns question with provided message', () => {
21
+ const message = 'Do you want to continue?';
22
+ const question = prompt_1.confirmationQuestion(message);
23
+ expect(question.message).toBe(message);
24
+ });
25
+ });
26
+ describe('datadogApiKeyTypeQuestion', () => {
27
+ test('returns question with message pointing to the correct given site', () => {
28
+ const site = 'datadoghq.com';
29
+ const question = prompt_1.datadogApiKeyTypeQuestion(site);
30
+ expect(question.message).toBe(`Which type of Datadog API Key you want to set? \nLearn more at ${chalk_1.blueBright(`https://app.${site}/organization-settings/api-keys`)}`);
31
+ });
32
+ });
33
+ describe('datadogEnvVarsQuestions', () => {
34
+ test('returns correct message when user selects DATADOG_API_KEY', () => {
35
+ const datadogApiKeyType = {
36
+ envVar: constants_1.CI_API_KEY_ENV_VAR,
37
+ message: 'API Key:',
38
+ };
39
+ const question = prompt_1.datadogEnvVarsQuestions(datadogApiKeyType);
40
+ expect(question.message).toBe('API Key:');
41
+ expect(question.name).toBe(constants_1.CI_API_KEY_ENV_VAR);
42
+ });
43
+ test('returns correct message when user selects DATADOG_KMS_API_KEY', () => {
44
+ const datadogApiKeyType = {
45
+ envVar: constants_1.CI_KMS_API_KEY_ENV_VAR,
46
+ message: 'KMS API Key:',
47
+ };
48
+ const question = prompt_1.datadogEnvVarsQuestions(datadogApiKeyType);
49
+ expect(question.message).toBe('KMS API Key:');
50
+ expect(question.name).toBe(constants_1.CI_KMS_API_KEY_ENV_VAR);
51
+ });
52
+ test('returns correct message when user selects DATADOG_API_KEY_SECRET_ARN', () => {
53
+ const datadogApiKeyType = {
54
+ envVar: constants_1.CI_API_KEY_SECRET_ARN_ENV_VAR,
55
+ message: 'API Key Secret ARN:',
56
+ };
57
+ const question = prompt_1.datadogEnvVarsQuestions(datadogApiKeyType);
58
+ expect(question.message).toBe('API Key Secret ARN:');
59
+ expect(question.name).toBe(constants_1.CI_API_KEY_SECRET_ARN_ENV_VAR);
60
+ });
61
+ });
62
+ describe('functionSelectionQuestion', () => {
63
+ test('returns question with the provided function names being its choices', () => {
64
+ const functionNames = ['my-func', 'my-func-2', 'my-third-func'];
65
+ const question = prompt_1.functionSelectionQuestion(functionNames);
66
+ expect(question.choices).toBe(functionNames);
67
+ });
68
+ });
69
+ describe('requestAWSCrendentials', () => {
70
+ const OLD_ENV = process.env;
71
+ beforeEach(() => {
72
+ jest.resetModules();
73
+ process.env = {};
74
+ });
75
+ afterAll(() => {
76
+ process.env = OLD_ENV;
77
+ });
78
+ test('sets the AWS credentials as environment variables', () => __awaiter(void 0, void 0, void 0, function* () {
79
+ ;
80
+ inquirer_1.prompt.mockImplementation(() => Promise.resolve({
81
+ [constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]: fixtures_1.mockAwsAccessKeyId,
82
+ [constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]: fixtures_1.mockAwsSecretAccessKey,
83
+ [constants_1.AWS_DEFAULT_REGION_ENV_VAR]: 'sa-east-1',
84
+ }));
85
+ yield prompt_1.requestAWSCredentials();
86
+ expect(process.env[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]).toBe(fixtures_1.mockAwsAccessKeyId);
87
+ expect(process.env[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]).toBe(fixtures_1.mockAwsSecretAccessKey);
88
+ expect(process.env[constants_1.AWS_DEFAULT_REGION_ENV_VAR]).toBe('sa-east-1');
89
+ }));
90
+ test('sets the AWS credentials with session token as environment variables', () => __awaiter(void 0, void 0, void 0, function* () {
91
+ ;
92
+ inquirer_1.prompt.mockImplementation(() => Promise.resolve({
93
+ [constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]: fixtures_1.mockAwsAccessKeyId,
94
+ [constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]: fixtures_1.mockAwsSecretAccessKey,
95
+ [constants_1.AWS_DEFAULT_REGION_ENV_VAR]: 'sa-east-1',
96
+ [constants_1.AWS_SESSION_TOKEN_ENV_VAR]: 'some-session-token',
97
+ }));
98
+ yield prompt_1.requestAWSCredentials();
99
+ expect(process.env[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]).toBe(fixtures_1.mockAwsAccessKeyId);
100
+ expect(process.env[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]).toBe(fixtures_1.mockAwsSecretAccessKey);
101
+ expect(process.env[constants_1.AWS_DEFAULT_REGION_ENV_VAR]).toBe('sa-east-1');
102
+ expect(process.env[constants_1.AWS_SESSION_TOKEN_ENV_VAR]).toBe('some-session-token');
103
+ }));
104
+ test('throws error when something unexpected happens while prompting', () => __awaiter(void 0, void 0, void 0, function* () {
105
+ ;
106
+ inquirer_1.prompt.mockImplementation(() => Promise.reject(new Error('Unexpected error')));
107
+ let error;
108
+ try {
109
+ yield prompt_1.requestAWSCredentials();
110
+ }
111
+ catch (e) {
112
+ if (e instanceof Error) {
113
+ error = e;
114
+ }
115
+ }
116
+ expect(error === null || error === void 0 ? void 0 : error.message).toBe("Couldn't set AWS Credentials. Unexpected error");
117
+ }));
118
+ });
119
+ describe('requestChangesConfirmation', () => {
120
+ test('returns boolean when users responds to confirmation question', () => __awaiter(void 0, void 0, void 0, function* () {
121
+ ;
122
+ inquirer_1.prompt.mockImplementation(() => Promise.resolve({
123
+ confirmation: true,
124
+ }));
125
+ const confirmation = yield prompt_1.requestChangesConfirmation('Do you want to continue?');
126
+ expect(confirmation).toBe(true);
127
+ }));
128
+ test('throws error when something unexpected happens while prompting', () => __awaiter(void 0, void 0, void 0, function* () {
129
+ ;
130
+ inquirer_1.prompt.mockImplementation(() => Promise.reject(new Error('Unexpected error')));
131
+ let error;
132
+ try {
133
+ yield prompt_1.requestChangesConfirmation('Do you wanna continue?');
134
+ }
135
+ catch (e) {
136
+ if (e instanceof Error) {
137
+ error = e;
138
+ }
139
+ }
140
+ expect(error === null || error === void 0 ? void 0 : error.message).toBe("Couldn't receive confirmation. Unexpected error");
141
+ }));
142
+ });
143
+ describe('requestDatadogEnvVars', () => {
144
+ const OLD_ENV = process.env;
145
+ beforeEach(() => {
146
+ jest.resetModules();
147
+ process.env = {};
148
+ });
149
+ afterAll(() => {
150
+ process.env = OLD_ENV;
151
+ });
152
+ test('sets the Datadog Environment Variables as provided/selected by user', () => __awaiter(void 0, void 0, void 0, function* () {
153
+ const site = 'datadoghq.com';
154
+ inquirer_1.prompt.mockImplementation((question) => {
155
+ switch (question.name) {
156
+ case constants_1.CI_API_KEY_ENV_VAR:
157
+ return Promise.resolve({
158
+ [constants_1.CI_API_KEY_ENV_VAR]: fixtures_1.mockDatadogApiKey,
159
+ });
160
+ case constants_1.CI_SITE_ENV_VAR:
161
+ return Promise.resolve({
162
+ [constants_1.CI_SITE_ENV_VAR]: 'datadoghq.com',
163
+ });
164
+ case 'type':
165
+ return Promise.resolve({
166
+ type: {
167
+ envVar: constants_1.CI_API_KEY_ENV_VAR,
168
+ message: 'API Key:',
169
+ },
170
+ });
171
+ default:
172
+ }
173
+ });
174
+ yield prompt_1.requestDatadogEnvVars();
175
+ expect(process.env[constants_1.CI_SITE_ENV_VAR]).toBe(site);
176
+ expect(process.env[constants_1.CI_API_KEY_ENV_VAR]).toBe(fixtures_1.mockDatadogApiKey);
177
+ }));
178
+ test('throws error when something unexpected happens while prompting', () => __awaiter(void 0, void 0, void 0, function* () {
179
+ ;
180
+ inquirer_1.prompt.mockImplementation(() => Promise.reject(new Error('Unexpected error')));
181
+ let error;
182
+ try {
183
+ yield prompt_1.requestDatadogEnvVars();
184
+ }
185
+ catch (e) {
186
+ if (e instanceof Error) {
187
+ error = e;
188
+ }
189
+ }
190
+ expect(error === null || error === void 0 ? void 0 : error.message).toBe("Couldn't set Datadog Environment Variables. Unexpected error");
191
+ }));
192
+ });
193
+ describe('requestFunctionSelection', () => {
194
+ const selectedFunctions = ['my-func', 'my-func-2', 'my-third-func'];
195
+ test('returns the selected functions', () => __awaiter(void 0, void 0, void 0, function* () {
196
+ ;
197
+ inquirer_1.prompt.mockImplementation(() => Promise.resolve({ functions: selectedFunctions }));
198
+ const functions = yield prompt_1.requestFunctionSelection(selectedFunctions);
199
+ expect(functions).toBe(selectedFunctions);
200
+ }));
201
+ test('throws error when something unexpected happens while prompting', () => __awaiter(void 0, void 0, void 0, function* () {
202
+ ;
203
+ inquirer_1.prompt.mockImplementation(() => Promise.reject(new Error('Unexpected error')));
204
+ let error;
205
+ try {
206
+ yield prompt_1.requestFunctionSelection(selectedFunctions);
207
+ }
208
+ catch (e) {
209
+ if (e instanceof Error) {
210
+ error = e;
211
+ }
212
+ }
213
+ expect(error === null || error === void 0 ? void 0 : error.message).toBe("Couldn't receive selected functions. Unexpected error");
214
+ }));
215
+ });
216
+ });
@@ -31,10 +31,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
31
31
  // tslint:disable: no-string-literal
32
32
  jest.mock('fs');
33
33
  jest.mock('aws-sdk');
34
+ jest.mock('../prompt');
34
35
  const aws_sdk_1 = require("aws-sdk");
35
36
  const chalk_1 = require("chalk");
36
37
  const fs = __importStar(require("fs"));
37
38
  const constants_1 = require("../constants");
39
+ const prompt_1 = require("../prompt");
38
40
  const uninstrument_1 = require("../uninstrument");
39
41
  const fixtures_1 = require("./fixtures");
40
42
  describe('uninstrument', () => {
@@ -52,6 +54,7 @@ describe('uninstrument', () => {
52
54
  fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
53
55
  aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({
54
56
  'arn:aws:lambda:us-east-1:000000000000:function:uninstrument': {
57
+ Architectures: ['x86_64'],
55
58
  Environment: {
56
59
  Variables: {
57
60
  [constants_1.ENVIRONMENT_ENV_VAR]: 'staging',
@@ -93,20 +96,22 @@ describe('uninstrument', () => {
93
96
  const output = context.stdout.toString();
94
97
  expect(code).toBe(0);
95
98
  expect(output).toMatchInlineSnapshot(`
96
- "${chalk_1.bold(chalk_1.cyan('[Dry Run] '))}Will apply the following updates:
97
- UpdateFunctionConfiguration -> arn:aws:lambda:us-east-1:000000000000:function:uninstrument
98
- {
99
- \\"FunctionName\\": \\"arn:aws:lambda:us-east-1:000000000000:function:uninstrument\\",
100
- \\"Handler\\": \\"lambda_function.lambda_handler\\",
101
- \\"Environment\\": {
102
- \\"Variables\\": {
103
- \\"USER_VARIABLE\\": \\"shouldnt be deleted by uninstrumentation\\"
104
- }
105
- },
106
- \\"Layers\\": []
107
- }
108
- "
109
- `);
99
+ "\n${chalk_1.bold(chalk_1.yellow('[!]'))} Functions to be updated:
100
+ \t- ${chalk_1.bold('arn:aws:lambda:us-east-1:000000000000:function:uninstrument')}\n
101
+ ${chalk_1.bold(chalk_1.cyan('[Dry Run] '))}Will apply the following updates:
102
+ UpdateFunctionConfiguration -> arn:aws:lambda:us-east-1:000000000000:function:uninstrument
103
+ {
104
+ \\"FunctionName\\": \\"arn:aws:lambda:us-east-1:000000000000:function:uninstrument\\",
105
+ \\"Handler\\": \\"lambda_function.lambda_handler\\",
106
+ \\"Environment\\": {
107
+ \\"Variables\\": {
108
+ \\"USER_VARIABLE\\": \\"shouldnt be deleted by uninstrumentation\\"
109
+ }
110
+ },
111
+ \\"Layers\\": []
112
+ }
113
+ "
114
+ `);
110
115
  }));
111
116
  test('runs function update command for valid uninstrumentation', () => __awaiter(void 0, void 0, void 0, function* () {
112
117
  ;
@@ -167,7 +172,7 @@ describe('uninstrument', () => {
167
172
  const code = yield command['execute']();
168
173
  const output = command.context.stdout.toString();
169
174
  expect(code).toBe(1);
170
- expect(output).toMatch(`${chalk_1.red('[Error]')} Couldn't fetch lambda functions. Lambda failed\n`);
175
+ expect(output).toMatch(`${chalk_1.red('[Error]')} Couldn't fetch Lambda functions. Lambda failed\n`);
171
176
  }));
172
177
  test("aborts early when function regions can't be found", () => __awaiter(void 0, void 0, void 0, function* () {
173
178
  ;
@@ -190,7 +195,7 @@ describe('uninstrument', () => {
190
195
  const output = context.stdout.toString();
191
196
  expect(code).toBe(1);
192
197
  expect(output).toMatchInlineSnapshot(`
193
- "No functions specified for un-instrumentation.
198
+ "${chalk_1.red('[Error]')} No functions specified for un-instrumentation.
194
199
  "
195
200
  `);
196
201
  }));
@@ -203,10 +208,369 @@ describe('uninstrument', () => {
203
208
  yield command['execute']();
204
209
  const output = command.context.stdout.toString();
205
210
  expect(output).toMatchInlineSnapshot(`
206
- "No functions specified for un-instrumentation.
211
+ "${chalk_1.red('[Error]')} No functions specified for un-instrumentation.
207
212
  "
208
213
  `);
209
214
  }));
215
+ test('aborts if functions and a pattern are set at the same time', () => __awaiter(void 0, void 0, void 0, function* () {
216
+ ;
217
+ fs.readFile.mockImplementation((a, b, callback) => callback({}));
218
+ process.env = {};
219
+ let command = fixtures_1.createCommand(uninstrument_1.UninstrumentCommand);
220
+ command['config']['region'] = 'ap-southeast-1';
221
+ command['config']['functions'] = ['arn:aws:lambda:ap-southeast-1:123456789012:function:lambda-hello-world'];
222
+ command['regExPattern'] = 'valid-pattern';
223
+ yield command['execute']();
224
+ let output = command.context.stdout.toString();
225
+ expect(output).toMatch('Functions in config file and "--functions-regex" should not be used at the same time.\n');
226
+ command = fixtures_1.createCommand(uninstrument_1.UninstrumentCommand);
227
+ command['region'] = 'ap-southeast-1';
228
+ command['functions'] = ['arn:aws:lambda:ap-southeast-1:123456789012:function:lambda-hello-world'];
229
+ command['regExPattern'] = 'valid-pattern';
230
+ yield command['execute']();
231
+ output = command.context.stdout.toString();
232
+ expect(output).toMatch('"--functions" and "--functions-regex" should not be used at the same time.\n');
233
+ }));
234
+ test('aborts if the regEx pattern is an ARN', () => __awaiter(void 0, void 0, void 0, function* () {
235
+ ;
236
+ fs.readFile.mockImplementation((a, b, callback) => callback({}));
237
+ process.env = {};
238
+ const command = fixtures_1.createCommand(uninstrument_1.UninstrumentCommand);
239
+ command['region'] = 'ap-southeast-1';
240
+ command['regExPattern'] = 'arn:aws:lambda:ap-southeast-1:123456789012:function:*';
241
+ const code = yield command['execute']();
242
+ const output = command.context.stdout.toString();
243
+ expect(code).toBe(1);
244
+ expect(output).toMatch(`"--functions-regex" isn't meant to be used with ARNs.\n`);
245
+ }));
246
+ test('aborts if the regEx pattern is set but no region is specified', () => __awaiter(void 0, void 0, void 0, function* () {
247
+ ;
248
+ fs.readFile.mockImplementation((a, b, callback) => callback({}));
249
+ process.env = {};
250
+ const command = fixtures_1.createCommand(uninstrument_1.UninstrumentCommand);
251
+ command['regExPattern'] = 'my-function';
252
+ const code = yield command['execute']();
253
+ const output = command.context.stdout.toString();
254
+ expect(code).toBe(1);
255
+ expect(output).toMatch('No default region specified. Use `-r`, `--region`.');
256
+ }));
257
+ test('aborts if the the aws-sdk fails', () => __awaiter(void 0, void 0, void 0, function* () {
258
+ ;
259
+ fs.readFile.mockImplementation((a, b, callback) => callback({}));
260
+ aws_sdk_1.Lambda.mockImplementation(() => ({ promise: Promise.reject() }));
261
+ process.env = {};
262
+ const command = fixtures_1.createCommand(uninstrument_1.UninstrumentCommand);
263
+ command['region'] = 'ap-southeast-1';
264
+ command['regExPattern'] = 'my-function';
265
+ const code = yield command['execute']();
266
+ const output = command.context.stdout.toString();
267
+ expect(code).toBe(1);
268
+ expect(output).toMatch(`Fetching Lambda functions, this might take a while.\n${chalk_1.red('[Error]')} Couldn't fetch Lambda functions. Error: Max retry count exceeded.\n`);
269
+ }));
270
+ test('uninstrument multiple functions interactively', () => __awaiter(void 0, void 0, void 0, function* () {
271
+ ;
272
+ fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
273
+ aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({
274
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world': {
275
+ Architectures: ['x86_64'],
276
+ Environment: {
277
+ Variables: {
278
+ [constants_1.ENVIRONMENT_ENV_VAR]: 'staging',
279
+ [constants_1.FLUSH_TO_LOG_ENV_VAR]: 'true',
280
+ [constants_1.LAMBDA_HANDLER_ENV_VAR]: 'lambda_function.lambda_handler',
281
+ [constants_1.LOG_LEVEL_ENV_VAR]: 'debug',
282
+ [constants_1.MERGE_XRAY_TRACES_ENV_VAR]: 'false',
283
+ [constants_1.SERVICE_ENV_VAR]: 'middletier',
284
+ [constants_1.SITE_ENV_VAR]: 'datadoghq.com',
285
+ [constants_1.TRACE_ENABLED_ENV_VAR]: 'true',
286
+ [constants_1.VERSION_ENV_VAR]: '0.2',
287
+ USER_VARIABLE: 'shouldnt be deleted by uninstrumentation',
288
+ },
289
+ },
290
+ FunctionArn: 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world',
291
+ FunctionName: 'lambda-hello-world',
292
+ Handler: 'datadog_lambda.handler.handler',
293
+ Layers: [
294
+ {
295
+ Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Extension:11',
296
+ CodeSize: 0,
297
+ SigningJobArn: 'some-signing-job-arn',
298
+ SigningProfileVersionArn: 'some-signing-profile',
299
+ },
300
+ {
301
+ Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Python38:49',
302
+ CodeSize: 0,
303
+ SigningJobArn: 'some-signing-job-arn',
304
+ SigningProfileVersionArn: 'some-signing-profile',
305
+ },
306
+ ],
307
+ Runtime: 'python3.8',
308
+ },
309
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2': {
310
+ Architectures: ['x86_64'],
311
+ Environment: {
312
+ Variables: {
313
+ [constants_1.ENVIRONMENT_ENV_VAR]: 'staging',
314
+ [constants_1.FLUSH_TO_LOG_ENV_VAR]: 'true',
315
+ [constants_1.LAMBDA_HANDLER_ENV_VAR]: 'lambda_function.lambda_handler',
316
+ [constants_1.LOG_LEVEL_ENV_VAR]: 'debug',
317
+ [constants_1.MERGE_XRAY_TRACES_ENV_VAR]: 'false',
318
+ [constants_1.SERVICE_ENV_VAR]: 'middletier',
319
+ [constants_1.SITE_ENV_VAR]: 'datadoghq.com',
320
+ [constants_1.TRACE_ENABLED_ENV_VAR]: 'true',
321
+ [constants_1.VERSION_ENV_VAR]: '0.2',
322
+ },
323
+ },
324
+ FunctionArn: 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2',
325
+ FunctionName: 'lambda-hello-world-2',
326
+ Handler: 'datadog_lambda.handler.handler',
327
+ Layers: [
328
+ {
329
+ Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Extension:11',
330
+ CodeSize: 0,
331
+ SigningJobArn: 'some-signing-job-arn',
332
+ SigningProfileVersionArn: 'some-signing-profile',
333
+ },
334
+ {
335
+ Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Python39:49',
336
+ CodeSize: 0,
337
+ SigningJobArn: 'some-signing-job-arn',
338
+ SigningProfileVersionArn: 'some-signing-profile',
339
+ },
340
+ ],
341
+ Runtime: 'python3.9',
342
+ },
343
+ }));
344
+ prompt_1.requestAWSCredentials.mockImplementation(() => {
345
+ process.env[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR] = fixtures_1.mockAwsAccessKeyId;
346
+ process.env[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR] = fixtures_1.mockAwsSecretAccessKey;
347
+ process.env[constants_1.AWS_DEFAULT_REGION_ENV_VAR] = 'sa-east-1';
348
+ });
349
+ prompt_1.requestFunctionSelection.mockImplementation(() => [
350
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world',
351
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2',
352
+ ]);
353
+ prompt_1.requestChangesConfirmation.mockImplementation(() => true);
354
+ const cli = fixtures_1.makeCli();
355
+ const context = fixtures_1.createMockContext();
356
+ const code = yield cli.run(['lambda', 'uninstrument', '-i'], context);
357
+ const output = context.stdout.toString();
358
+ expect(code).toBe(0);
359
+ expect(output).toMatchInlineSnapshot(`
360
+ "${chalk_1.bold(chalk_1.yellow('[!]'))} No existing AWS credentials found, let's set them up!
361
+ Fetching Lambda functions, this might take a while.\n
362
+ ${chalk_1.bold(chalk_1.yellow('[!]'))} Functions to be updated:
363
+ \t- ${chalk_1.bold('arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world')}
364
+ \t- ${chalk_1.bold('arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2')}\n
365
+ Will apply the following updates:
366
+ UpdateFunctionConfiguration -> arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world
367
+ {
368
+ \\"FunctionName\\": \\"arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world\\",
369
+ \\"Handler\\": \\"lambda_function.lambda_handler\\",
370
+ \\"Environment\\": {
371
+ \\"Variables\\": {
372
+ \\"USER_VARIABLE\\": \\"shouldnt be deleted by uninstrumentation\\"
373
+ }
374
+ },
375
+ \\"Layers\\": []
376
+ }
377
+ UpdateFunctionConfiguration -> arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2
378
+ {
379
+ \\"FunctionName\\": \\"arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2\\",
380
+ \\"Handler\\": \\"lambda_function.lambda_handler\\",
381
+ \\"Environment\\": {
382
+ \\"Variables\\": {}
383
+ },
384
+ \\"Layers\\": []
385
+ }
386
+ ${chalk_1.yellow('[!]')} Confirmation needed.
387
+ ${chalk_1.yellow('[!]')} Uninstrumenting functions.
388
+ "
389
+ `);
390
+ }));
391
+ test('uninstrument multiple specified functions interactively', () => __awaiter(void 0, void 0, void 0, function* () {
392
+ ;
393
+ fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
394
+ aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({
395
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world': {
396
+ Architectures: ['x86_64'],
397
+ Environment: {
398
+ Variables: {
399
+ [constants_1.ENVIRONMENT_ENV_VAR]: 'staging',
400
+ [constants_1.FLUSH_TO_LOG_ENV_VAR]: 'true',
401
+ [constants_1.LAMBDA_HANDLER_ENV_VAR]: 'lambda_function.lambda_handler',
402
+ [constants_1.LOG_LEVEL_ENV_VAR]: 'debug',
403
+ [constants_1.MERGE_XRAY_TRACES_ENV_VAR]: 'false',
404
+ [constants_1.SERVICE_ENV_VAR]: 'middletier',
405
+ [constants_1.SITE_ENV_VAR]: 'datadoghq.com',
406
+ [constants_1.TRACE_ENABLED_ENV_VAR]: 'true',
407
+ [constants_1.VERSION_ENV_VAR]: '0.2',
408
+ USER_VARIABLE: 'shouldnt be deleted by uninstrumentation',
409
+ },
410
+ },
411
+ FunctionArn: 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world',
412
+ FunctionName: 'lambda-hello-world',
413
+ Handler: 'datadog_lambda.handler.handler',
414
+ Layers: [
415
+ {
416
+ Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Extension:11',
417
+ CodeSize: 0,
418
+ SigningJobArn: 'some-signing-job-arn',
419
+ SigningProfileVersionArn: 'some-signing-profile',
420
+ },
421
+ {
422
+ Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Python38:49',
423
+ CodeSize: 0,
424
+ SigningJobArn: 'some-signing-job-arn',
425
+ SigningProfileVersionArn: 'some-signing-profile',
426
+ },
427
+ ],
428
+ Runtime: 'python3.8',
429
+ },
430
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2': {
431
+ Architectures: ['x86_64'],
432
+ Environment: {
433
+ Variables: {
434
+ [constants_1.ENVIRONMENT_ENV_VAR]: 'staging',
435
+ [constants_1.FLUSH_TO_LOG_ENV_VAR]: 'true',
436
+ [constants_1.LAMBDA_HANDLER_ENV_VAR]: 'lambda_function.lambda_handler',
437
+ [constants_1.LOG_LEVEL_ENV_VAR]: 'debug',
438
+ [constants_1.MERGE_XRAY_TRACES_ENV_VAR]: 'false',
439
+ [constants_1.SERVICE_ENV_VAR]: 'middletier',
440
+ [constants_1.SITE_ENV_VAR]: 'datadoghq.com',
441
+ [constants_1.TRACE_ENABLED_ENV_VAR]: 'true',
442
+ [constants_1.VERSION_ENV_VAR]: '0.2',
443
+ },
444
+ },
445
+ FunctionArn: 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2',
446
+ FunctionName: 'lambda-hello-world-2',
447
+ Handler: 'datadog_lambda.handler.handler',
448
+ Layers: [
449
+ {
450
+ Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Extension:11',
451
+ CodeSize: 0,
452
+ SigningJobArn: 'some-signing-job-arn',
453
+ SigningProfileVersionArn: 'some-signing-profile',
454
+ },
455
+ {
456
+ Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Python39:49',
457
+ CodeSize: 0,
458
+ SigningJobArn: 'some-signing-job-arn',
459
+ SigningProfileVersionArn: 'some-signing-profile',
460
+ },
461
+ ],
462
+ Runtime: 'python3.9',
463
+ },
464
+ }));
465
+ prompt_1.requestAWSCredentials.mockImplementation(() => {
466
+ process.env[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR] = fixtures_1.mockAwsAccessKeyId;
467
+ process.env[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR] = fixtures_1.mockAwsSecretAccessKey;
468
+ process.env[constants_1.AWS_DEFAULT_REGION_ENV_VAR] = 'sa-east-1';
469
+ });
470
+ prompt_1.requestFunctionSelection.mockImplementation(() => [
471
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world',
472
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2',
473
+ ]);
474
+ prompt_1.requestChangesConfirmation.mockImplementation(() => true);
475
+ const cli = fixtures_1.makeCli();
476
+ const context = fixtures_1.createMockContext();
477
+ const code = yield cli.run([
478
+ 'lambda',
479
+ 'uninstrument',
480
+ '-i',
481
+ '-f',
482
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world',
483
+ '-f',
484
+ 'arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2',
485
+ ], context);
486
+ const output = context.stdout.toString();
487
+ expect(code).toBe(0);
488
+ expect(output).toMatchInlineSnapshot(`
489
+ "${chalk_1.bold(chalk_1.yellow('[!]'))} No existing AWS credentials found, let's set them up!\n
490
+ ${chalk_1.bold(chalk_1.yellow('[!]'))} Functions to be updated:
491
+ \t- ${chalk_1.bold('arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world')}
492
+ \t- ${chalk_1.bold('arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2')}\n
493
+ Will apply the following updates:
494
+ UpdateFunctionConfiguration -> arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world
495
+ {
496
+ \\"FunctionName\\": \\"arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world\\",
497
+ \\"Handler\\": \\"lambda_function.lambda_handler\\",
498
+ \\"Environment\\": {
499
+ \\"Variables\\": {
500
+ \\"USER_VARIABLE\\": \\"shouldnt be deleted by uninstrumentation\\"
501
+ }
502
+ },
503
+ \\"Layers\\": []
504
+ }
505
+ UpdateFunctionConfiguration -> arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2
506
+ {
507
+ \\"FunctionName\\": \\"arn:aws:lambda:sa-east-1:123456789012:function:lambda-hello-world-2\\",
508
+ \\"Handler\\": \\"lambda_function.lambda_handler\\",
509
+ \\"Environment\\": {
510
+ \\"Variables\\": {}
511
+ },
512
+ \\"Layers\\": []
513
+ }
514
+ ${chalk_1.yellow('[!]')} Confirmation needed.
515
+ ${chalk_1.yellow('[!]')} Uninstrumenting functions.
516
+ "
517
+ `);
518
+ }));
519
+ test('aborts if a problem occurs while setting the AWS credentials interactively', () => __awaiter(void 0, void 0, void 0, function* () {
520
+ ;
521
+ fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
522
+ prompt_1.requestAWSCredentials.mockImplementation(() => Promise.reject('Unexpected error'));
523
+ const cli = fixtures_1.makeCli();
524
+ const context = fixtures_1.createMockContext();
525
+ const code = yield cli.run(['lambda', 'uninstrument', '-i'], context);
526
+ const output = context.stdout.toString();
527
+ expect(code).toBe(1);
528
+ expect(output).toMatchInlineSnapshot(`
529
+ "${chalk_1.bold(chalk_1.yellow('[!]'))} No existing AWS credentials found, let's set them up!
530
+ ${chalk_1.red('[Error]')} Unexpected error
531
+ "
532
+ `);
533
+ }));
534
+ test('aborts if there are no functions to uninstrument in the user AWS account', () => __awaiter(void 0, void 0, void 0, function* () {
535
+ process.env = {
536
+ [constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]: fixtures_1.mockAwsAccessKeyId,
537
+ [constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]: fixtures_1.mockAwsSecretAccessKey,
538
+ [constants_1.AWS_DEFAULT_REGION_ENV_VAR]: 'sa-east-1',
539
+ };
540
+ fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
541
+ aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({}));
542
+ const cli = fixtures_1.makeCli();
543
+ const context = fixtures_1.createMockContext();
544
+ const code = yield cli.run(['lambda', 'uninstrument', '-i'], context);
545
+ const output = context.stdout.toString();
546
+ expect(code).toBe(1);
547
+ expect(output).toMatchInlineSnapshot(`
548
+ "Fetching Lambda functions, this might take a while.
549
+ ${chalk_1.red('[Error]')} Couldn't find any Lambda functions in the specified region.
550
+ "
551
+ `);
552
+ }));
553
+ test('aborts early when the aws-sdk throws an error while uninstrumenting interactively', () => __awaiter(void 0, void 0, void 0, function* () {
554
+ process.env = {
555
+ [constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]: fixtures_1.mockAwsAccessKeyId,
556
+ [constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]: fixtures_1.mockAwsSecretAccessKey,
557
+ [constants_1.AWS_DEFAULT_REGION_ENV_VAR]: 'sa-east-1',
558
+ };
559
+ fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
560
+ aws_sdk_1.Lambda.mockImplementation(() => ({
561
+ listFunctions: jest.fn().mockImplementation(() => ({ promise: () => Promise.reject('Lambda failed') })),
562
+ }));
563
+ const cli = fixtures_1.makeCli();
564
+ const context = fixtures_1.createMockContext();
565
+ const code = yield cli.run(['lambda', 'uninstrument', '-i'], context);
566
+ const output = context.stdout.toString();
567
+ expect(code).toBe(1);
568
+ expect(output).toMatchInlineSnapshot(`
569
+ "Fetching Lambda functions, this might take a while.
570
+ ${chalk_1.red('[Error]')} Couldn't fetch Lambda functions. Error: Max retry count exceeded.
571
+ "
572
+ `);
573
+ }));
210
574
  });
211
575
  describe('printPlannedActions', () => {
212
576
  test('prints no output when list is empty', () => {