@datadog/datadog-ci 0.17.8 → 0.17.12

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 (80) hide show
  1. package/LICENSE-3rdparty.csv +2 -0
  2. package/README.md +3 -1
  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/__tests__/function.test.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/lambda/__tests__/fixtures.d.ts +42 -0
  19. package/dist/commands/lambda/__tests__/fixtures.js +73 -0
  20. package/dist/commands/lambda/{index.d.ts → __tests__/functions/commons.test.d.ts} +0 -0
  21. package/dist/commands/lambda/__tests__/functions/commons.test.js +350 -0
  22. package/dist/commands/{sourcemaps/index.d.ts → lambda/__tests__/functions/instrument.test.d.ts} +0 -0
  23. package/dist/commands/lambda/__tests__/{function.test.js → functions/instrument.test.js} +504 -476
  24. package/dist/commands/{trace/index.d.ts → lambda/__tests__/functions/uninstrument.test.d.ts} +0 -0
  25. package/dist/commands/lambda/__tests__/functions/uninstrument.test.js +371 -0
  26. package/dist/commands/lambda/__tests__/instrument.test.js +351 -234
  27. package/dist/commands/lambda/__tests__/loggroup.test.js +98 -34
  28. package/dist/commands/lambda/__tests__/tags.test.js +107 -31
  29. package/dist/commands/lambda/__tests__/uninstrument.test.d.ts +1 -0
  30. package/dist/commands/lambda/__tests__/uninstrument.test.js +281 -0
  31. package/dist/commands/lambda/cli.d.ts +1 -0
  32. package/dist/commands/lambda/cli.js +5 -0
  33. package/dist/commands/lambda/constants.d.ts +18 -6
  34. package/dist/commands/lambda/constants.js +30 -6
  35. package/dist/commands/lambda/functions/commons.d.ts +101 -0
  36. package/dist/commands/lambda/functions/commons.js +258 -0
  37. package/dist/commands/lambda/functions/instrument.d.ts +7 -0
  38. package/dist/commands/lambda/functions/instrument.js +186 -0
  39. package/dist/commands/lambda/functions/uninstrument.d.ts +7 -0
  40. package/dist/commands/lambda/functions/uninstrument.js +121 -0
  41. package/dist/commands/lambda/instrument.d.ts +4 -4
  42. package/dist/commands/lambda/instrument.js +103 -57
  43. package/dist/commands/lambda/interfaces.d.ts +53 -0
  44. package/dist/commands/lambda/loggroup.d.ts +4 -7
  45. package/dist/commands/lambda/loggroup.js +30 -5
  46. package/dist/commands/lambda/tags.d.ts +3 -4
  47. package/dist/commands/lambda/tags.js +19 -3
  48. package/dist/commands/lambda/uninstrument.d.ts +12 -0
  49. package/dist/commands/lambda/uninstrument.js +166 -0
  50. package/dist/commands/sourcemaps/cli.d.ts +1 -0
  51. package/dist/commands/sourcemaps/{index.js → cli.js} +0 -0
  52. package/dist/commands/sourcemaps/upload.d.ts +1 -1
  53. package/dist/commands/synthetics/__tests__/cli.test.js +35 -13
  54. package/dist/commands/synthetics/__tests__/utils.test.js +0 -4
  55. package/dist/commands/synthetics/__tests__/websocket.test.js +3 -3
  56. package/dist/commands/synthetics/cli.d.ts +1 -26
  57. package/dist/commands/synthetics/cli.js +2 -227
  58. package/dist/commands/synthetics/command.d.ts +26 -0
  59. package/dist/commands/synthetics/command.js +230 -0
  60. package/dist/commands/synthetics/index.d.ts +5 -1
  61. package/dist/commands/synthetics/index.js +31 -2
  62. package/dist/commands/synthetics/utils.d.ts +0 -3
  63. package/dist/commands/synthetics/utils.js +1 -11
  64. package/dist/commands/trace/cli.d.ts +1 -0
  65. package/dist/commands/trace/{index.js → cli.js} +0 -0
  66. package/dist/commands/trace/trace.d.ts +1 -1
  67. package/dist/helpers/__tests__/ci.test.js +51 -114
  68. package/dist/helpers/__tests__/user-provided-git.test.js +14 -2
  69. package/dist/helpers/__tests__/utils.test.js +4 -0
  70. package/dist/helpers/ci.js +62 -96
  71. package/dist/helpers/interfaces.d.ts +28 -2
  72. package/dist/helpers/user-provided-git.js +11 -2
  73. package/dist/helpers/utils.d.ts +4 -0
  74. package/dist/helpers/utils.js +18 -1
  75. package/dist/index.d.ts +3 -1
  76. package/dist/index.js +23 -31
  77. package/package.json +10 -8
  78. package/dist/commands/lambda/function.d.ts +0 -43
  79. package/dist/commands/lambda/function.js +0 -273
  80. package/dist/commands/lambda/index.js +0 -4
@@ -7,6 +7,7 @@ Component,Origin,Licence,Copyright
7
7
  @types/tiny-async-pool,dev,MIT,Copyright (c) Microsoft Corporation
8
8
  @types/deep-extend,dev,MIT,Copyright Microsoft Corporation
9
9
  @types/glob,dev,MIT,Copyright Microsoft Corporation
10
+ @types/inquirer,dev,MIT,Copyright Microsoft Corporation
10
11
  @types/jest,dev,MIT,Copyright Microsoft Corporation
11
12
  @types/node,dev,MIT,Copyright Microsoft Corporation
12
13
  @types/ssh2,dev,MIT,Copyright Microsoft Corporation
@@ -25,6 +26,7 @@ deep-extend,import,MIT,Copyright (c) 2013-2018, Viacheslav Lotsmanov
25
26
  fast-xml-parser,import,MIT,Copyright (c) 2017 Amit Kumar Gupta
26
27
  form-data,import,MIT,Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
27
28
  glob,import,ISC,Copyright (c) Isaac Z. Schlueter and Contributors
29
+ inquirer,import,MIT,Copyright (c) 2012 Simon Boudrias
28
30
  jest,dev,MIT,Copyright (c) Facebook, Inc. and its affiliates.
29
31
  jest-environment-node,dev,MIT,Copyright (c) Facebook, Inc. and its affiliates.
30
32
  jest-matcher-specific-error,dev,MIT,Copyright (c) 2020 Daniel Hreben
package/README.md CHANGED
@@ -33,12 +33,13 @@ yarn global add @datadog/datadog-ci
33
33
  ```bash
34
34
  Usage: datadog-ci <command> <subcommand> [options]
35
35
 
36
- Available command:
36
+ Available commands:
37
37
  - dependencies
38
38
  - lambda
39
39
  - sourcemaps
40
40
  - synthetics
41
41
  - dsyms
42
+ - git-metadata
42
43
  ```
43
44
 
44
45
  Each command allows interacting with a product of the Datadog platform. The commands are defined in the [src/commands](/src/commands) folder.
@@ -50,6 +51,7 @@ Further documentation for each command can be found in its folder, ie:
50
51
  - [Sourcemaps](src/commands/sourcemaps/)
51
52
  - [Synthetics CI/CD Testing](src/commands/synthetics/)
52
53
  - [iOS dSYM Files](src/commands/dsyms/)
54
+ - [Git metadata](src/commands/git-metadata)
53
55
 
54
56
  ## Contributing
55
57
 
package/dist/cli.js ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const clipanion_1 = require("clipanion");
9
+ const onError = (err) => {
10
+ console.log(err);
11
+ process.exitCode = 1;
12
+ };
13
+ process.on('uncaughtException', onError);
14
+ process.on('unhandledRejection', onError);
15
+ const cli = new clipanion_1.Cli({
16
+ binaryLabel: 'Datadog CI',
17
+ binaryName: 'datadog-ci',
18
+ binaryVersion: require('../package.json').version,
19
+ });
20
+ const commandsPath = `${__dirname}/commands`;
21
+ for (const commandFolder of fs_1.default.readdirSync(commandsPath)) {
22
+ const commandPath = `${commandsPath}/${commandFolder}`;
23
+ if (fs_1.default.statSync(commandPath).isDirectory()) {
24
+ // tslint:disable-next-line: no-var-requires
25
+ require(`${commandPath}/cli`).forEach((command) => cli.register(command));
26
+ }
27
+ }
28
+ if (require.main === module) {
29
+ cli.runExit(process.argv.slice(2), {
30
+ stderr: process.stderr,
31
+ stdin: process.stdin,
32
+ stdout: process.stdout,
33
+ });
34
+ }
File without changes
@@ -1,7 +1,7 @@
1
1
  import { Command } from 'clipanion';
2
2
  export declare class UploadCommand extends Command {
3
3
  static SUPPORTED_SOURCES: string[];
4
- static usage: import("clipanion/lib/advanced").Usage;
4
+ static usage: import("clipanion").Usage;
5
5
  private static INVALID_INPUT_EXIT_CODE;
6
6
  private static MISSING_FILE_EXIT_CODE;
7
7
  private static UPLOAD_ERROR_EXIT_CODE;
File without changes
@@ -1,6 +1,6 @@
1
1
  import { Command } from 'clipanion';
2
2
  export declare class UploadCommand extends Command {
3
- static usage: import("clipanion/lib/advanced").Usage;
3
+ static usage: import("clipanion").Usage;
4
4
  private basePath;
5
5
  private config;
6
6
  private dryRun;
File without changes
@@ -1,6 +1,6 @@
1
1
  import { Command } from 'clipanion';
2
2
  export declare class UploadCommand extends Command {
3
- static usage: import("clipanion/lib/advanced").Usage;
3
+ static usage: import("clipanion").Usage;
4
4
  repositoryURL?: string;
5
5
  private cliVersion;
6
6
  private config;
@@ -51,7 +51,7 @@ class UploadCommand extends clipanion_1.Command {
51
51
  });
52
52
  const payload = yield git_1.getCommitInfo(yield git_1.newSimpleGit(), this.context.stdout, this.repositoryURL);
53
53
  if (payload === undefined) {
54
- return 0;
54
+ return 1;
55
55
  }
56
56
  this.context.stdout.write(renderer_1.renderCommandInfo(payload));
57
57
  try {
@@ -106,6 +106,11 @@ class UploadCommand extends clipanion_1.Command {
106
106
  return utils_1.getRequestBuilder({
107
107
  apiKey: this.config.apiKey,
108
108
  baseUrl: api_1.getBaseIntakeUrl(),
109
+ headers: new Map([
110
+ ['DD-EVP-ORIGIN', 'datadog-ci git-metadata'],
111
+ ['DD-EVP-ORIGIN-VERSION', this.cliVersion],
112
+ ]),
113
+ overrideUrl: 'api/v2/srcmap',
109
114
  });
110
115
  }
111
116
  uploadRepository(requestBuilder) {
File without changes
@@ -1,6 +1,6 @@
1
1
  import { Command } from 'clipanion';
2
2
  export declare class UploadJUnitXMLCommand extends Command {
3
- static usage: import("clipanion/lib/advanced").Usage;
3
+ static usage: import("clipanion").Usage;
4
4
  private basePaths?;
5
5
  private config;
6
6
  private dryRun;
@@ -0,0 +1,42 @@
1
+ /// <reference types="jest" />
2
+ import { CloudWatchLogs, Lambda } from 'aws-sdk';
3
+ import { Cli, Command } from 'clipanion/lib/advanced';
4
+ export declare const createMockContext: () => {
5
+ stdout: {
6
+ toString: () => string;
7
+ write: (input: string) => void;
8
+ };
9
+ };
10
+ export declare const makeCli: () => Cli<import("clipanion/lib/advanced").BaseContext>;
11
+ /**
12
+ * Allow for constructors with any amount of parameters.
13
+ * Mainly used for testing when we are creating commands.
14
+ */
15
+ export declare type ConstructorOf<T> = new (...args: any[]) => T;
16
+ /**
17
+ * Allows to create an instance of any command that
18
+ * extends the Command clss.
19
+ *
20
+ * @param commandClass any class that extends the Command class.
21
+ * @param parameters parameters to use while creating the commandClass
22
+ * @returns the instance of the given command with a mock context attatched.
23
+ */
24
+ export declare const createCommand: <T extends Command<import("clipanion/lib/advanced").BaseContext>>(commandClass: ConstructorOf<T>, ...parameters: any[]) => T;
25
+ export declare const makeMockLambda: (functionConfigs: Record<string, Lambda.FunctionConfiguration>) => {
26
+ getFunction: jest.Mock<any, any>;
27
+ listFunctions: jest.Mock<any, any>;
28
+ listTags: jest.Mock<any, any>;
29
+ tagResource: jest.Mock<any, any>;
30
+ updateFunctionConfiguration: jest.Mock<any, any>;
31
+ };
32
+ export declare const makeMockCloudWatchLogs: (logGroups: Record<string, {
33
+ config: CloudWatchLogs.DescribeLogGroupsResponse;
34
+ filters?: CloudWatchLogs.DescribeSubscriptionFiltersResponse;
35
+ }>) => {
36
+ createLogGroup: jest.Mock<any, any>;
37
+ deleteSubscriptionFilter: jest.Mock<any, any>;
38
+ describeLogGroups: jest.Mock<any, any>;
39
+ describeSubscriptionFilters: jest.Mock<any, any>;
40
+ putSubscriptionFilter: jest.Mock<any, any>;
41
+ };
42
+ export declare const mockAwsAccount = "123456789012";
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mockAwsAccount = exports.makeMockCloudWatchLogs = exports.makeMockLambda = exports.createCommand = exports.makeCli = exports.createMockContext = void 0;
4
+ const advanced_1 = require("clipanion/lib/advanced");
5
+ const instrument_1 = require("../instrument");
6
+ const uninstrument_1 = require("../uninstrument");
7
+ const createMockContext = () => {
8
+ let data = '';
9
+ return {
10
+ stdout: {
11
+ toString: () => data,
12
+ write: (input) => {
13
+ data += input;
14
+ },
15
+ },
16
+ };
17
+ };
18
+ exports.createMockContext = createMockContext;
19
+ const makeCli = () => {
20
+ const cli = new advanced_1.Cli();
21
+ cli.register(instrument_1.InstrumentCommand);
22
+ cli.register(uninstrument_1.UninstrumentCommand);
23
+ return cli;
24
+ };
25
+ exports.makeCli = makeCli;
26
+ /**
27
+ * Allows to create an instance of any command that
28
+ * extends the Command clss.
29
+ *
30
+ * @param commandClass any class that extends the Command class.
31
+ * @param parameters parameters to use while creating the commandClass
32
+ * @returns the instance of the given command with a mock context attatched.
33
+ */
34
+ const createCommand = (commandClass, ...parameters) => {
35
+ // Create a new instance of commandClass and pass in the parameters
36
+ const command = new commandClass(...parameters);
37
+ command.context = exports.createMockContext();
38
+ return command;
39
+ };
40
+ exports.createCommand = createCommand;
41
+ const makeMockLambda = (functionConfigs) => ({
42
+ getFunction: jest.fn().mockImplementation(({ FunctionName }) => ({
43
+ promise: () => Promise.resolve({ Configuration: functionConfigs[FunctionName] }),
44
+ })),
45
+ listFunctions: jest.fn().mockImplementation(() => ({
46
+ promise: () => Promise.resolve({ Functions: Object.values(functionConfigs) }),
47
+ })),
48
+ listTags: jest.fn().mockImplementation(() => ({ promise: () => Promise.resolve({ Tags: {} }) })),
49
+ tagResource: jest.fn().mockImplementation(() => ({ promise: () => Promise.resolve() })),
50
+ updateFunctionConfiguration: jest.fn().mockImplementation(() => ({ promise: () => Promise.resolve() })),
51
+ });
52
+ exports.makeMockLambda = makeMockLambda;
53
+ const makeMockCloudWatchLogs = (logGroups) => ({
54
+ createLogGroup: jest.fn().mockImplementation(() => ({ promise: () => Promise.resolve() })),
55
+ deleteSubscriptionFilter: jest.fn().mockImplementation(() => ({ promise: () => Promise.resolve() })),
56
+ describeLogGroups: jest.fn().mockImplementation(({ logGroupNamePrefix }) => {
57
+ var _a, _b;
58
+ const groups = (_b = (_a = logGroups[logGroupNamePrefix]) === null || _a === void 0 ? void 0 : _a.config) !== null && _b !== void 0 ? _b : { logGroups: [] };
59
+ return {
60
+ promise: () => Promise.resolve(groups),
61
+ };
62
+ }),
63
+ describeSubscriptionFilters: jest.fn().mockImplementation(({ logGroupName }) => {
64
+ var _a, _b;
65
+ const groups = (_b = (_a = logGroups[logGroupName]) === null || _a === void 0 ? void 0 : _a.filters) !== null && _b !== void 0 ? _b : { subscriptionFilters: [] };
66
+ return {
67
+ promise: () => Promise.resolve(groups),
68
+ };
69
+ }),
70
+ putSubscriptionFilter: jest.fn().mockImplementation(() => ({ promise: () => Promise.resolve() })),
71
+ });
72
+ exports.makeMockCloudWatchLogs = makeMockCloudWatchLogs;
73
+ exports.mockAwsAccount = '123456789012';
@@ -0,0 +1,350 @@
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
+ /* tslint:disable:no-string-literal */
13
+ const constants_1 = require("../../constants");
14
+ const commons_1 = require("../../functions/commons");
15
+ const instrument_1 = require("../../instrument");
16
+ const fixtures_1 = require("../fixtures");
17
+ describe('commons', () => {
18
+ describe('addLayerArn', () => {
19
+ test('adds layers and removes previous versions', () => {
20
+ const runtime = 'python3.9';
21
+ const config = {
22
+ Runtime: runtime,
23
+ };
24
+ let layerARNs = [
25
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Python39:48',
26
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Extension:10',
27
+ ];
28
+ const region = 'sa-east-1';
29
+ const lambdaLibraryLayerName = constants_1.RUNTIME_LAYER_LOOKUP[runtime];
30
+ const fullLambdaLibraryLayerArn = commons_1.getLayerArn(config, config.Runtime, region) + ':49';
31
+ const fullExtensionLayerArn = commons_1.getLayerArn(config, constants_1.EXTENSION_LAYER_KEY, region) + ':11';
32
+ layerARNs = commons_1.addLayerArn(fullLambdaLibraryLayerArn, lambdaLibraryLayerName, layerARNs);
33
+ layerARNs = commons_1.addLayerArn(fullExtensionLayerArn, constants_1.DD_LAMBDA_EXTENSION_LAYER_NAME, layerARNs);
34
+ expect(layerARNs).toEqual([
35
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Python39:49',
36
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Extension:11',
37
+ ]);
38
+ });
39
+ test('swaps layers if architecture is arm64', () => {
40
+ const runtime = 'python3.9';
41
+ const config = {
42
+ Architectures: ['arm64'],
43
+ Runtime: runtime,
44
+ };
45
+ let layerARNs = [
46
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Python39:49',
47
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Extension:11',
48
+ ];
49
+ const region = 'sa-east-1';
50
+ const lambdaLibraryLayerName = constants_1.RUNTIME_LAYER_LOOKUP[runtime];
51
+ const fullLambdaLibraryLayerArn = commons_1.getLayerArn(config, config.Runtime, region) + ':49';
52
+ const fullExtensionLayerArn = commons_1.getLayerArn(config, constants_1.EXTENSION_LAYER_KEY, region) + ':11';
53
+ layerARNs = commons_1.addLayerArn(fullLambdaLibraryLayerArn, lambdaLibraryLayerName, layerARNs);
54
+ layerARNs = commons_1.addLayerArn(fullExtensionLayerArn, constants_1.DD_LAMBDA_EXTENSION_LAYER_NAME, layerARNs);
55
+ expect(layerARNs).toEqual([
56
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Python39-ARM:49',
57
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Extension-ARM:11',
58
+ ]);
59
+ });
60
+ });
61
+ describe('coerceBoolean', () => {
62
+ test('return fallback when none of the values provided can be parsed to boolean', () => {
63
+ expect(commons_1.coerceBoolean(true, 'NotBoolean', 123, [], {})).toBe(true);
64
+ expect(commons_1.coerceBoolean(false, 'NotBooleanEither', 456, ['An array'], { booleanInObject: true })).toBe(false);
65
+ });
66
+ test('return the first boolean when one of the values provided can be parsed to boolean', () => {
67
+ expect(commons_1.coerceBoolean(true, 'false', 'true')).toBe(false);
68
+ expect(commons_1.coerceBoolean(false, 'true', 'False')).toBe(true);
69
+ });
70
+ test('return the first boolean when one of the values provided is boolean', () => {
71
+ expect(commons_1.coerceBoolean(true, false, 'truE', true)).toBe(false);
72
+ expect(commons_1.coerceBoolean(false, true, 'False', false)).toBe(true);
73
+ });
74
+ });
75
+ describe('collectFunctionsByRegion', () => {
76
+ test('groups functions with region read from arn', () => {
77
+ process.env = {};
78
+ const command = fixtures_1.createCommand(instrument_1.InstrumentCommand);
79
+ const region = 'us-east-1';
80
+ command['functions'] = [
81
+ 'arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world',
82
+ 'arn:aws:lambda:us-east-1:123456789012:function:another',
83
+ 'arn:aws:lambda:us-east-2:123456789012:function:third-func',
84
+ ];
85
+ expect(commons_1.collectFunctionsByRegion(command['functions'], region)).toEqual({
86
+ 'us-east-1': [
87
+ 'arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world',
88
+ 'arn:aws:lambda:us-east-1:123456789012:function:another',
89
+ ],
90
+ 'us-east-2': ['arn:aws:lambda:us-east-2:123456789012:function:third-func'],
91
+ });
92
+ });
93
+ test('groups functions in the config object', () => {
94
+ process.env = {};
95
+ const command = fixtures_1.createCommand(instrument_1.InstrumentCommand);
96
+ const region = 'us-east-1';
97
+ command['config']['functions'] = [
98
+ 'arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world',
99
+ 'arn:aws:lambda:us-east-1:123456789012:function:another',
100
+ 'arn:aws:lambda:us-east-2:123456789012:function:third-func',
101
+ ];
102
+ expect(commons_1.collectFunctionsByRegion(command['config']['functions'], region)).toEqual({
103
+ 'us-east-1': [
104
+ 'arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world',
105
+ 'arn:aws:lambda:us-east-1:123456789012:function:another',
106
+ ],
107
+ 'us-east-2': ['arn:aws:lambda:us-east-2:123456789012:function:third-func'],
108
+ });
109
+ });
110
+ test('uses default region for functions not in arn format', () => {
111
+ process.env = {};
112
+ const command = fixtures_1.createCommand(instrument_1.InstrumentCommand);
113
+ command['functions'] = [
114
+ 'arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world',
115
+ 'arn:aws:lambda:*:123456789012:function:func-with-wildcard',
116
+ 'func-without-region',
117
+ 'arn:aws:lambda:us-east-2:123456789012:function:third-func',
118
+ ];
119
+ command['region'] = 'ap-south-1';
120
+ expect(commons_1.collectFunctionsByRegion(command['functions'], command['region'])).toEqual({
121
+ 'ap-south-1': ['arn:aws:lambda:*:123456789012:function:func-with-wildcard', 'func-without-region'],
122
+ 'us-east-1': ['arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world'],
123
+ 'us-east-2': ['arn:aws:lambda:us-east-2:123456789012:function:third-func'],
124
+ });
125
+ });
126
+ test('fails to collect when there are regionless functions and no default region is set', () => {
127
+ process.env = {};
128
+ const command = fixtures_1.createCommand(instrument_1.InstrumentCommand);
129
+ command['functions'] = [
130
+ 'arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world',
131
+ 'arn:aws:lambda:*:123456789012:function:func-with-wildcard',
132
+ 'func-without-region',
133
+ 'arn:aws:lambda:us-east-2:123456789012:function:third-func',
134
+ ];
135
+ command['region'] = undefined;
136
+ command['config']['region'] = undefined;
137
+ let functionsGroup;
138
+ try {
139
+ functionsGroup = commons_1.collectFunctionsByRegion(command['functions'], command['region']);
140
+ }
141
+ catch (err) {
142
+ // Do nothing
143
+ }
144
+ expect(functionsGroup).toBeUndefined();
145
+ });
146
+ });
147
+ describe('getLayerArn', () => {
148
+ const OLD_ENV = process.env;
149
+ beforeEach(() => {
150
+ jest.resetModules();
151
+ process.env = {};
152
+ });
153
+ afterAll(() => {
154
+ process.env = OLD_ENV;
155
+ });
156
+ test('gets sa-east-1 Lambda Extension layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
157
+ const settings = {
158
+ flushMetricsToLogs: false,
159
+ layerAWSAccount: fixtures_1.mockAwsAccount,
160
+ mergeXrayTraces: false,
161
+ tracingEnabled: false,
162
+ };
163
+ const region = 'sa-east-1';
164
+ const layerArn = commons_1.getLayerArn({}, constants_1.EXTENSION_LAYER_KEY, region, settings);
165
+ expect(layerArn).toEqual(`arn:aws:lambda:${region}:${fixtures_1.mockAwsAccount}:layer:Datadog-Extension`);
166
+ }));
167
+ test('gets sa-east-1 arm64 Lambda Extension layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
168
+ const config = {
169
+ Architectures: ['arm64'],
170
+ };
171
+ const settings = {
172
+ flushMetricsToLogs: false,
173
+ layerAWSAccount: fixtures_1.mockAwsAccount,
174
+ mergeXrayTraces: false,
175
+ tracingEnabled: false,
176
+ };
177
+ const region = 'sa-east-1';
178
+ const layerArn = commons_1.getLayerArn(config, constants_1.EXTENSION_LAYER_KEY, region, settings);
179
+ expect(layerArn).toEqual(`arn:aws:lambda:${region}:${fixtures_1.mockAwsAccount}:layer:Datadog-Extension-ARM`);
180
+ }));
181
+ test('gets us-gov-1 gov cloud Lambda Extension layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
182
+ const settings = {
183
+ flushMetricsToLogs: false,
184
+ layerAWSAccount: fixtures_1.mockAwsAccount,
185
+ mergeXrayTraces: false,
186
+ tracingEnabled: false,
187
+ };
188
+ const region = 'us-gov-1';
189
+ const layerArn = commons_1.getLayerArn({}, constants_1.EXTENSION_LAYER_KEY, region, settings);
190
+ expect(layerArn).toEqual(`arn:aws-us-gov:lambda:${region}:${constants_1.GOVCLOUD_LAYER_AWS_ACCOUNT}:layer:Datadog-Extension`);
191
+ }));
192
+ test('gets us-gov-1 gov cloud arm64 Lambda Extension layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
193
+ const config = {
194
+ Architectures: ['arm64'],
195
+ };
196
+ const settings = {
197
+ flushMetricsToLogs: false,
198
+ layerAWSAccount: fixtures_1.mockAwsAccount,
199
+ mergeXrayTraces: false,
200
+ tracingEnabled: false,
201
+ };
202
+ const region = 'us-gov-1';
203
+ const layerArn = commons_1.getLayerArn(config, constants_1.EXTENSION_LAYER_KEY, region, settings);
204
+ expect(layerArn).toEqual(`arn:aws-us-gov:lambda:${region}:${constants_1.GOVCLOUD_LAYER_AWS_ACCOUNT}:layer:Datadog-Extension-ARM`);
205
+ }));
206
+ test('gets sa-east-1 Node12 Lambda Library layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
207
+ const runtime = 'nodejs12.x';
208
+ const config = {
209
+ Runtime: runtime,
210
+ };
211
+ const settings = {
212
+ flushMetricsToLogs: false,
213
+ layerAWSAccount: fixtures_1.mockAwsAccount,
214
+ mergeXrayTraces: false,
215
+ tracingEnabled: false,
216
+ };
217
+ const region = 'sa-east-1';
218
+ const layerArn = commons_1.getLayerArn(config, config.Runtime, region, settings);
219
+ expect(layerArn).toEqual(`arn:aws:lambda:${region}:${fixtures_1.mockAwsAccount}:layer:Datadog-Node12-x`);
220
+ }));
221
+ test('gets sa-east-1 Python3.9 arm64 Lambda Library layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
222
+ const runtime = 'python3.9';
223
+ const config = {
224
+ Architectures: ['arm64'],
225
+ Runtime: runtime,
226
+ };
227
+ const settings = {
228
+ flushMetricsToLogs: false,
229
+ layerAWSAccount: fixtures_1.mockAwsAccount,
230
+ mergeXrayTraces: false,
231
+ tracingEnabled: false,
232
+ };
233
+ const region = 'sa-east-1';
234
+ const layerArn = commons_1.getLayerArn(config, config.Runtime, region, settings);
235
+ expect(layerArn).toEqual(`arn:aws:lambda:${region}:${fixtures_1.mockAwsAccount}:layer:Datadog-Python39-ARM`);
236
+ }));
237
+ test('gets us-gov-1 Python37 gov cloud Lambda Library layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
238
+ const runtime = 'python3.7';
239
+ const config = {
240
+ Runtime: runtime,
241
+ };
242
+ const settings = {
243
+ flushMetricsToLogs: false,
244
+ layerAWSAccount: fixtures_1.mockAwsAccount,
245
+ mergeXrayTraces: false,
246
+ tracingEnabled: false,
247
+ };
248
+ const region = 'us-gov-1';
249
+ const layerArn = commons_1.getLayerArn(config, config.Runtime, region, settings);
250
+ expect(layerArn).toEqual(`arn:aws-us-gov:lambda:${region}:${constants_1.GOVCLOUD_LAYER_AWS_ACCOUNT}:layer:Datadog-Python37`);
251
+ }));
252
+ test('gets us-gov-1 Python39 gov cloud arm64 Lambda Library layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
253
+ const runtime = 'python3.9';
254
+ const config = {
255
+ Architectures: ['arm64'],
256
+ Runtime: runtime,
257
+ };
258
+ const settings = {
259
+ flushMetricsToLogs: false,
260
+ layerAWSAccount: fixtures_1.mockAwsAccount,
261
+ mergeXrayTraces: false,
262
+ tracingEnabled: false,
263
+ };
264
+ const region = 'us-gov-1';
265
+ const layerArn = commons_1.getLayerArn(config, config.Runtime, region, settings);
266
+ expect(layerArn).toEqual(`arn:aws-us-gov:lambda:${region}:${constants_1.GOVCLOUD_LAYER_AWS_ACCOUNT}:layer:Datadog-Python39-ARM`);
267
+ }));
268
+ });
269
+ describe('getRegion', () => {
270
+ test('should return the expected region', () => {
271
+ const functionARN = 'arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world';
272
+ const expectedRegion = 'us-east-1';
273
+ const region = commons_1.getRegion(functionARN);
274
+ expect(region).toBe(expectedRegion);
275
+ });
276
+ test('should return undefined if Function ARN does not contain the region', () => {
277
+ const functionName = 'lambda-hello-world';
278
+ const region = commons_1.getRegion(functionName);
279
+ expect(region).toBe(undefined);
280
+ });
281
+ });
282
+ describe('sentenceMatchesRegEx', () => {
283
+ const tags = [
284
+ ['not-complying:regex-should-fail', false],
285
+ ['1first-char-is-number:should-fail', false],
286
+ ['_also-not-complying:should-fail', false],
287
+ ['complying_tag:accepted/with/slashes.and.dots,but-empty-tag', false],
288
+ ['also_complying:success,1but_is_illegal:should-fail', false],
289
+ ['this:complies,also_this_one:yes,numb3r_in_name:should-succeed,dots:al.lo.wed', true],
290
+ ['complying_ip_address_4:192.342.3134.231', true],
291
+ ['complying:alone', true],
292
+ ['one_divided_by_two:1/2,one_divided_by_four:0.25,three_minus_one_half:3-1/2', true],
293
+ ['this_is_a_valid_t4g:yes/it.is-42', true],
294
+ ];
295
+ test.each(tags)('check if the tags match the expected result from the regex', (tag, expectedResult) => {
296
+ const result = !!commons_1.sentenceMatchesRegEx(tag, constants_1.EXTRA_TAGS_REG_EXP);
297
+ expect(result).toEqual(expectedResult);
298
+ });
299
+ });
300
+ describe('updateLambdaConfigs', () => {
301
+ const OLD_ENV = process.env;
302
+ beforeEach(() => {
303
+ jest.resetModules();
304
+ process.env = {};
305
+ });
306
+ afterAll(() => {
307
+ process.env = OLD_ENV;
308
+ });
309
+ test('updates every lambda', () => __awaiter(void 0, void 0, void 0, function* () {
310
+ const lambda = fixtures_1.makeMockLambda({});
311
+ const configs = [
312
+ {
313
+ functionARN: 'arn:aws:lambda:us-east-1:000000000000:function:autoinstrument',
314
+ lambdaConfig: {
315
+ FunctionArn: 'arn:aws:lambda:us-east-1:000000000000:function:autoinstrument',
316
+ Handler: 'index.handler',
317
+ Runtime: 'nodejs12.x',
318
+ },
319
+ lambdaLibraryLayerArn: 'arn:aws:lambda:us-east-1:464622532012:layer:Datadog-Node12-x',
320
+ updateRequest: {
321
+ Environment: {
322
+ Variables: {
323
+ [constants_1.LAMBDA_HANDLER_ENV_VAR]: 'index.handler',
324
+ [constants_1.MERGE_XRAY_TRACES_ENV_VAR]: 'false',
325
+ [constants_1.TRACE_ENABLED_ENV_VAR]: 'false',
326
+ },
327
+ },
328
+ FunctionName: 'arn:aws:lambda:us-east-1:000000000000:function:autoinstrument',
329
+ Handler: '/opt/nodejs/node_modules/datadog-lambda-js/handler.handler',
330
+ Layers: ['arn:aws:lambda:us-east-1:464622532012:layer:Datadog-Node12-x:22'],
331
+ },
332
+ },
333
+ ];
334
+ const cloudWatch = fixtures_1.makeMockCloudWatchLogs({});
335
+ yield commons_1.updateLambdaFunctionConfigs(lambda, cloudWatch, configs);
336
+ expect(lambda.updateFunctionConfiguration).toHaveBeenCalledWith({
337
+ Environment: {
338
+ Variables: {
339
+ [constants_1.LAMBDA_HANDLER_ENV_VAR]: 'index.handler',
340
+ [constants_1.MERGE_XRAY_TRACES_ENV_VAR]: 'false',
341
+ [constants_1.TRACE_ENABLED_ENV_VAR]: 'false',
342
+ },
343
+ },
344
+ FunctionName: 'arn:aws:lambda:us-east-1:000000000000:function:autoinstrument',
345
+ Handler: '/opt/nodejs/node_modules/datadog-lambda-js/handler.handler',
346
+ Layers: ['arn:aws:lambda:us-east-1:464622532012:layer:Datadog-Node12-x:22'],
347
+ });
348
+ }));
349
+ });
350
+ });