@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
@@ -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
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![Continuous Integration](https://github.com/DataDog/datadog-ci/workflows/Continuous%20Integration/badge.svg) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ![NodeJS Version](https://img.shields.io/badge/Node.js-10.24.1+-green)
4
4
 
5
- Execute commands with Datadog from within your Continuous Integration/Continuous Deployment scripts. A good way to perform end to end tests of your application before applying you changes or deploying. It currently features running synthetics tests and waiting for the results.
5
+ Execute commands with Datadog from within your Continuous Integration/Continuous Deployment scripts. A good way to perform end to end tests of your application before applying your changes or deploying. It currently features running synthetics tests and waiting for the results.
6
6
 
7
7
  ## How to install the CLI
8
8
 
@@ -28,17 +28,21 @@ npm install -g @datadog/datadog-ci
28
28
  # Yarn v1 add globally
29
29
  yarn global add @datadog/datadog-ci
30
30
  ```
31
+
31
32
  ## Usage
32
33
 
33
34
  ```bash
34
35
  Usage: datadog-ci <command> <subcommand> [options]
35
36
 
36
- Available command:
37
+ Available commands:
37
38
  - dependencies
38
39
  - lambda
39
40
  - sourcemaps
40
41
  - synthetics
41
42
  - dsyms
43
+ - git-metadata
44
+ - junit
45
+ - trace
42
46
  ```
43
47
 
44
48
  Each command allows interacting with a product of the Datadog platform. The commands are defined in the [src/commands](/src/commands) folder.
@@ -50,6 +54,9 @@ Further documentation for each command can be found in its folder, ie:
50
54
  - [Sourcemaps](src/commands/sourcemaps/)
51
55
  - [Synthetics CI/CD Testing](src/commands/synthetics/)
52
56
  - [iOS dSYM Files](src/commands/dsyms/)
57
+ - [Git metadata](src/commands/git-metadata)
58
+ - [JUnit XML](src/commands/junit)
59
+ - [Trace](src/commands/trace)
53
60
 
54
61
  ## Contributing
55
62
 
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;
@@ -100,7 +100,7 @@ class UploadJUnitXMLCommand extends clipanion_1.Command {
100
100
  }, []);
101
101
  const ciSpanTags = ci_1.getCISpanTags();
102
102
  const gitSpanTags = yield git_1.getGitMetadata();
103
- const userGitSpanTags = user_provided_git_1.getUserGitMetadata();
103
+ const userGitSpanTags = user_provided_git_1.getUserGitSpanTags();
104
104
  const envVarTags = this.config.envVarTags ? tags_1.parseTags(this.config.envVarTags.split(',')) : {};
105
105
  const cliTags = this.tags ? tags_1.parseTags(this.tags) : {};
106
106
  const spanTags = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, gitSpanTags), ciSpanTags), userGitSpanTags), cliTags), envVarTags), (this.config.env ? { env: this.config.env } : {}));
@@ -22,8 +22,9 @@ export declare type ConstructorOf<T> = new (...args: any[]) => T;
22
22
  * @returns the instance of the given command with a mock context attatched.
23
23
  */
24
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>) => {
25
+ export declare const makeMockLambda: (functionConfigs: Record<string, Lambda.FunctionConfiguration>, layers?: Record<string, Lambda.LayerVersionsListItem> | undefined) => {
26
26
  getFunction: jest.Mock<any, any>;
27
+ getLayerVersion: jest.Mock<any, any>;
27
28
  listFunctions: jest.Mock<any, any>;
28
29
  listTags: jest.Mock<any, any>;
29
30
  tagResource: jest.Mock<any, any>;
@@ -40,3 +41,6 @@ export declare const makeMockCloudWatchLogs: (logGroups: Record<string, {
40
41
  putSubscriptionFilter: jest.Mock<any, any>;
41
42
  };
42
43
  export declare const mockAwsAccount = "123456789012";
44
+ export declare const mockAwsAccessKeyId = "M0CKAWS4CC3SSK3Y1DSL";
45
+ export declare const mockAwsSecretAccessKey = "M0CKAWSs3cR3T4cC3SSK3YS3rv3rL3SSD4tad0g0";
46
+ export declare const mockDatadogApiKey = "02aeb762fff59ac0d5ad1536cd9633bd";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mockAwsAccount = exports.makeMockCloudWatchLogs = exports.makeMockLambda = exports.createCommand = exports.makeCli = exports.createMockContext = void 0;
3
+ exports.mockDatadogApiKey = exports.mockAwsSecretAccessKey = exports.mockAwsAccessKeyId = exports.mockAwsAccount = exports.makeMockCloudWatchLogs = exports.makeMockLambda = exports.createCommand = exports.makeCli = exports.createMockContext = void 0;
4
4
  const advanced_1 = require("clipanion/lib/advanced");
5
5
  const instrument_1 = require("../instrument");
6
6
  const uninstrument_1 = require("../uninstrument");
@@ -38,10 +38,18 @@ const createCommand = (commandClass, ...parameters) => {
38
38
  return command;
39
39
  };
40
40
  exports.createCommand = createCommand;
41
- const makeMockLambda = (functionConfigs) => ({
41
+ const makeMockLambda = (functionConfigs, layers) => ({
42
42
  getFunction: jest.fn().mockImplementation(({ FunctionName }) => ({
43
43
  promise: () => Promise.resolve({ Configuration: functionConfigs[FunctionName] }),
44
44
  })),
45
+ getLayerVersion: jest.fn().mockImplementation(({ LayerName, VersionNumber }) => ({
46
+ promise: () => {
47
+ const layer = LayerName + ':' + VersionNumber;
48
+ return layers && layers[layer] && layers[layer].Version === VersionNumber
49
+ ? Promise.resolve(layers[layer])
50
+ : Promise.reject();
51
+ },
52
+ })),
45
53
  listFunctions: jest.fn().mockImplementation(() => ({
46
54
  promise: () => Promise.resolve({ Functions: Object.values(functionConfigs) }),
47
55
  })),
@@ -71,3 +79,6 @@ const makeMockCloudWatchLogs = (logGroups) => ({
71
79
  });
72
80
  exports.makeMockCloudWatchLogs = makeMockCloudWatchLogs;
73
81
  exports.mockAwsAccount = '123456789012';
82
+ exports.mockAwsAccessKeyId = 'M0CKAWS4CC3SSK3Y1DSL';
83
+ exports.mockAwsSecretAccessKey = 'M0CKAWSs3cR3T4cC3SSK3YS3rv3rL3SSD4tad0g0';
84
+ exports.mockDatadogApiKey = '02aeb762fff59ac0d5ad1536cd9633bd';
@@ -10,11 +10,70 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  /* tslint:disable:no-string-literal */
13
+ jest.mock('aws-sdk');
14
+ const aws_sdk_1 = require("aws-sdk");
13
15
  const constants_1 = require("../../constants");
14
16
  const commons_1 = require("../../functions/commons");
15
17
  const instrument_1 = require("../../instrument");
16
18
  const fixtures_1 = require("../fixtures");
17
19
  describe('commons', () => {
20
+ describe('addLayerArn', () => {
21
+ test('adds layers and removes previous versions', () => {
22
+ const runtime = 'python3.9';
23
+ const config = {
24
+ Runtime: runtime,
25
+ };
26
+ let layerARNs = [
27
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Python39:48',
28
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Extension:10',
29
+ ];
30
+ const region = 'sa-east-1';
31
+ const lambdaLibraryLayerName = constants_1.RUNTIME_LAYER_LOOKUP[runtime];
32
+ const fullLambdaLibraryLayerArn = commons_1.getLayerArn(config, config.Runtime, region) + ':49';
33
+ const fullExtensionLayerArn = commons_1.getLayerArn(config, constants_1.EXTENSION_LAYER_KEY, region) + ':11';
34
+ layerARNs = commons_1.addLayerArn(fullLambdaLibraryLayerArn, lambdaLibraryLayerName, layerARNs);
35
+ layerARNs = commons_1.addLayerArn(fullExtensionLayerArn, constants_1.DD_LAMBDA_EXTENSION_LAYER_NAME, layerARNs);
36
+ expect(layerARNs).toEqual([
37
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Python39:49',
38
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Extension:11',
39
+ ]);
40
+ });
41
+ test('swaps layers if architecture is arm64', () => {
42
+ const runtime = 'python3.9';
43
+ const config = {
44
+ Architectures: ['arm64'],
45
+ Runtime: runtime,
46
+ };
47
+ let layerARNs = [
48
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Python39:49',
49
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Extension:11',
50
+ ];
51
+ const region = 'sa-east-1';
52
+ const lambdaLibraryLayerName = constants_1.RUNTIME_LAYER_LOOKUP[runtime];
53
+ const fullLambdaLibraryLayerArn = commons_1.getLayerArn(config, config.Runtime, region) + ':49';
54
+ const fullExtensionLayerArn = commons_1.getLayerArn(config, constants_1.EXTENSION_LAYER_KEY, region) + ':11';
55
+ layerARNs = commons_1.addLayerArn(fullLambdaLibraryLayerArn, lambdaLibraryLayerName, layerARNs);
56
+ layerARNs = commons_1.addLayerArn(fullExtensionLayerArn, constants_1.DD_LAMBDA_EXTENSION_LAYER_NAME, layerARNs);
57
+ expect(layerARNs).toEqual([
58
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Python39-ARM:49',
59
+ 'arn:aws:lambda:sa-east-1:464622532012:layer:Datadog-Extension-ARM:11',
60
+ ]);
61
+ });
62
+ });
63
+ describe('coerceBoolean', () => {
64
+ test('return fallback when none of the values provided can be parsed to boolean', () => {
65
+ expect(commons_1.coerceBoolean(true, 'NotBoolean', 123, [], {})).toBe(true);
66
+ expect(commons_1.coerceBoolean(false, 'NotBooleanEither', 456, ['An array'], { booleanInObject: true })).toBe(false);
67
+ });
68
+ test('return the first boolean when one of the values provided can be parsed to boolean', () => {
69
+ expect(commons_1.coerceBoolean(true, 'false', 'true')).toBe(false);
70
+ expect(commons_1.coerceBoolean(false, 'true', 'False')).toBe(true);
71
+ });
72
+ test('return the first boolean when one of the values provided is boolean', () => {
73
+ expect(commons_1.coerceBoolean(true, false, 'truE', true)).toBe(false);
74
+ expect(commons_1.coerceBoolean(false, true, 'False', false)).toBe(true);
75
+ });
76
+ });
18
77
  describe('collectFunctionsByRegion', () => {
19
78
  test('groups functions with region read from arn', () => {
20
79
  process.env = {};
@@ -87,6 +146,347 @@ describe('commons', () => {
87
146
  expect(functionsGroup).toBeUndefined();
88
147
  });
89
148
  });
149
+ describe('findLatestLayerVersion', () => {
150
+ test('finds latests version for Python39', () => __awaiter(void 0, void 0, void 0, function* () {
151
+ const layer = `arn:aws:lambda:sa-east-1:${constants_1.DEFAULT_LAYER_AWS_ACCOUNT}:layer:Datadog-Python39`;
152
+ aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({}, {
153
+ [`${layer}:1`]: {
154
+ LayerVersionArn: `${layer}:1`,
155
+ Version: 1,
156
+ },
157
+ [`${layer}:2`]: {
158
+ LayerVersionArn: `${layer}:2`,
159
+ Version: 2,
160
+ },
161
+ [`${layer}:10`]: {
162
+ LayerVersionArn: `${layer}:10`,
163
+ Version: 10,
164
+ },
165
+ [`${layer}:20`]: {
166
+ LayerVersionArn: `${layer}:20`,
167
+ Version: 20,
168
+ },
169
+ [`${layer}:30`]: {
170
+ LayerVersionArn: `${layer}:30`,
171
+ Version: 30,
172
+ },
173
+ [`${layer}:31`]: {
174
+ LayerVersionArn: `${layer}:31`,
175
+ Version: 31,
176
+ },
177
+ [`${layer}:32`]: {
178
+ LayerVersionArn: `${layer}:32`,
179
+ Version: 32,
180
+ },
181
+ }));
182
+ const runtime = 'python3.9';
183
+ const region = 'sa-east-1';
184
+ const expectedLatestVersion = 32;
185
+ const latestVersionFound = yield commons_1.findLatestLayerVersion(runtime, region);
186
+ expect(latestVersionFound).toBe(expectedLatestVersion);
187
+ }));
188
+ test('finds latests version for Node14', () => __awaiter(void 0, void 0, void 0, function* () {
189
+ const layer = `arn:aws:lambda:us-east-1:${constants_1.DEFAULT_LAYER_AWS_ACCOUNT}:layer:Datadog-Node14-x`;
190
+ aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({}, {
191
+ [`${layer}:1`]: {
192
+ LayerVersionArn: `${layer}:1`,
193
+ Version: 1,
194
+ },
195
+ [`${layer}:10`]: {
196
+ LayerVersionArn: `${layer}:10`,
197
+ Version: 10,
198
+ },
199
+ [`${layer}:20`]: {
200
+ LayerVersionArn: `${layer}:20`,
201
+ Version: 20,
202
+ },
203
+ [`${layer}:30`]: {
204
+ LayerVersionArn: `${layer}:30`,
205
+ Version: 30,
206
+ },
207
+ [`${layer}:40`]: {
208
+ LayerVersionArn: `${layer}:40`,
209
+ Version: 40,
210
+ },
211
+ [`${layer}:41`]: {
212
+ LayerVersionArn: `${layer}:41`,
213
+ Version: 41,
214
+ },
215
+ }));
216
+ const runtime = 'nodejs14.x';
217
+ const region = 'us-east-1';
218
+ const expectedLatestVersion = 41;
219
+ const latestVersionFound = yield commons_1.findLatestLayerVersion(runtime, region);
220
+ expect(latestVersionFound).toBe(expectedLatestVersion);
221
+ }));
222
+ test('returns 0 when no layer can be found', () => __awaiter(void 0, void 0, void 0, function* () {
223
+ ;
224
+ aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({}, {}));
225
+ const runtime = 'python3.7';
226
+ const region = 'us-east-1';
227
+ const expectedLatestVersion = 0;
228
+ const latestVersionFound = yield commons_1.findLatestLayerVersion(runtime, region);
229
+ expect(latestVersionFound).toBe(expectedLatestVersion);
230
+ }));
231
+ });
232
+ describe('isMissingAWSCredentials', () => {
233
+ const OLD_ENV = process.env;
234
+ beforeEach(() => {
235
+ jest.resetModules();
236
+ process.env = {};
237
+ });
238
+ afterAll(() => {
239
+ process.env = OLD_ENV;
240
+ });
241
+ test('returns true when any AWS credential is missing', () => {
242
+ process.env[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR] = 'SOME-AWS-SECRET-ACCESS-KEY';
243
+ expect(commons_1.isMissingAWSCredentials()).toBe(true);
244
+ // Reset env
245
+ process.env = {};
246
+ process.env[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR] = 'SOME-AWS-ACCESS-KEY-ID';
247
+ expect(commons_1.isMissingAWSCredentials()).toBe(true);
248
+ });
249
+ test('returns false when AWS credentials are set', () => {
250
+ process.env[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR] = 'SOME-AWS-ACCESS-KEY-ID';
251
+ process.env[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR] = 'SOME-AWS-SECRET-ACCESS-KEY';
252
+ expect(commons_1.isMissingAWSCredentials()).toBe(false);
253
+ });
254
+ });
255
+ describe('isMissingDatadogEnvVars', () => {
256
+ const OLD_ENV = process.env;
257
+ beforeEach(() => {
258
+ jest.resetModules();
259
+ process.env = {};
260
+ });
261
+ afterAll(() => {
262
+ process.env = OLD_ENV;
263
+ });
264
+ test('returns true when any Datadog Env Var is missing', () => {
265
+ process.env[constants_1.CI_SITE_ENV_VAR] = 'datadoghq.com';
266
+ expect(commons_1.isMissingDatadogEnvVars()).toBe(true);
267
+ // Reset env
268
+ process.env = {};
269
+ process.env[constants_1.CI_API_KEY_ENV_VAR] = 'SOME-DATADOG-API-KEY';
270
+ expect(commons_1.isMissingDatadogEnvVars()).toBe(true);
271
+ process.env = {};
272
+ process.env[constants_1.CI_KMS_API_KEY_ENV_VAR] = 'SOME-AWS-KMS-API-KEY-CONTAINING-DATADOG-API-KEY';
273
+ expect(commons_1.isMissingDatadogEnvVars()).toBe(true);
274
+ process.env = {};
275
+ process.env[constants_1.CI_API_KEY_SECRET_ARN_ENV_VAR] = 'SOME-AWS-SECRET-ARN-CONTAINING-DATADOG-API-KEY';
276
+ expect(commons_1.isMissingDatadogEnvVars()).toBe(true);
277
+ });
278
+ test('returns false when Datadog Env Vars are set with DATADOG_API_KEY', () => {
279
+ process.env[constants_1.CI_API_KEY_ENV_VAR] = 'SOME-DATADOG-API-KEY';
280
+ process.env[constants_1.CI_SITE_ENV_VAR] = 'datadoghq.com';
281
+ expect(commons_1.isMissingDatadogEnvVars()).toBe(false);
282
+ });
283
+ test('returns false when Datadog Env Vars are set with DATADOG_KMS_API_KEY', () => {
284
+ process.env[constants_1.CI_KMS_API_KEY_ENV_VAR] = 'SOME-AWS-KMS-API-KEY-CONTAINING-DATADOG-API-KEY';
285
+ process.env[constants_1.CI_SITE_ENV_VAR] = 'datadoghq.com';
286
+ expect(commons_1.isMissingDatadogEnvVars()).toBe(false);
287
+ });
288
+ test('returns false when Datadog Env Vars are set with DATADOG_API_KEY_SECRET_ARN', () => {
289
+ process.env[constants_1.CI_API_KEY_SECRET_ARN_ENV_VAR] = 'SOME-AWS-SECRET-ARN-CONTAINING-DATADOG-API-KEY';
290
+ process.env[constants_1.CI_SITE_ENV_VAR] = 'datadoghq.com';
291
+ expect(commons_1.isMissingDatadogEnvVars()).toBe(false);
292
+ });
293
+ });
294
+ describe('isMissingDatadogSiteEnvVar', () => {
295
+ const OLD_ENV = process.env;
296
+ beforeEach(() => {
297
+ jest.resetModules();
298
+ process.env = {};
299
+ });
300
+ afterAll(() => {
301
+ process.env = OLD_ENV;
302
+ });
303
+ test('returns true when Datadog Site Env Var is missing', () => {
304
+ expect(commons_1.isMissingDatadogSiteEnvVar()).toBe(true);
305
+ });
306
+ test('returns false when Datadog Site Env Var is set', () => {
307
+ process.env[constants_1.CI_SITE_ENV_VAR] = 'datadoghq.com';
308
+ expect(commons_1.isMissingDatadogSiteEnvVar()).toBe(false);
309
+ });
310
+ test('returns true when Datadog Site Env Var is set and is not a valid Datadog site', () => {
311
+ process.env[constants_1.CI_SITE_ENV_VAR] = 'datacathq.com';
312
+ expect(commons_1.isMissingDatadogSiteEnvVar()).toBe(true);
313
+ });
314
+ });
315
+ describe('isMissingAnyDatadogApiKeyEnvVar', () => {
316
+ const OLD_ENV = process.env;
317
+ beforeEach(() => {
318
+ jest.resetModules();
319
+ process.env = {};
320
+ });
321
+ afterAll(() => {
322
+ process.env = OLD_ENV;
323
+ });
324
+ test('returns true when no Datadog Api Key is set', () => {
325
+ expect(commons_1.isMissingAnyDatadogApiKeyEnvVar()).toBe(true);
326
+ });
327
+ test('returns false when DATADOG_API_KEY is set', () => {
328
+ process.env[constants_1.CI_API_KEY_ENV_VAR] = 'SOME-DATADOG-API-KEY';
329
+ expect(commons_1.isMissingAnyDatadogApiKeyEnvVar()).toBe(false);
330
+ });
331
+ test('returns false when DATADOG_KMS_API_KEY is set', () => {
332
+ process.env[constants_1.CI_KMS_API_KEY_ENV_VAR] = 'SOME-AWS-KMS-API-KEY-CONTAINING-DATADOG-API-KEY';
333
+ expect(commons_1.isMissingAnyDatadogApiKeyEnvVar()).toBe(false);
334
+ });
335
+ test('returns false when DATADOG_API_KEY_SECRET_ARN is set', () => {
336
+ process.env[constants_1.CI_API_KEY_SECRET_ARN_ENV_VAR] = 'SOME-AWS-SECRET-ARN-CONTAINING-DATADOG-API-KEY';
337
+ expect(commons_1.isMissingAnyDatadogApiKeyEnvVar()).toBe(false);
338
+ });
339
+ });
340
+ describe('getLayerArn', () => {
341
+ const OLD_ENV = process.env;
342
+ beforeEach(() => {
343
+ jest.resetModules();
344
+ process.env = {};
345
+ });
346
+ afterAll(() => {
347
+ process.env = OLD_ENV;
348
+ });
349
+ test('gets sa-east-1 Lambda Extension layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
350
+ const settings = {
351
+ flushMetricsToLogs: false,
352
+ layerAWSAccount: fixtures_1.mockAwsAccount,
353
+ mergeXrayTraces: false,
354
+ tracingEnabled: false,
355
+ };
356
+ const region = 'sa-east-1';
357
+ const layerArn = commons_1.getLayerArn({}, constants_1.EXTENSION_LAYER_KEY, region, settings);
358
+ expect(layerArn).toEqual(`arn:aws:lambda:${region}:${fixtures_1.mockAwsAccount}:layer:Datadog-Extension`);
359
+ }));
360
+ test('gets sa-east-1 arm64 Lambda Extension layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
361
+ const config = {
362
+ Architectures: ['arm64'],
363
+ };
364
+ const settings = {
365
+ flushMetricsToLogs: false,
366
+ layerAWSAccount: fixtures_1.mockAwsAccount,
367
+ mergeXrayTraces: false,
368
+ tracingEnabled: false,
369
+ };
370
+ const region = 'sa-east-1';
371
+ const layerArn = commons_1.getLayerArn(config, constants_1.EXTENSION_LAYER_KEY, region, settings);
372
+ expect(layerArn).toEqual(`arn:aws:lambda:${region}:${fixtures_1.mockAwsAccount}:layer:Datadog-Extension-ARM`);
373
+ }));
374
+ test('gets us-gov-1 gov cloud Lambda Extension layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
375
+ const settings = {
376
+ flushMetricsToLogs: false,
377
+ layerAWSAccount: fixtures_1.mockAwsAccount,
378
+ mergeXrayTraces: false,
379
+ tracingEnabled: false,
380
+ };
381
+ const region = 'us-gov-1';
382
+ const layerArn = commons_1.getLayerArn({}, constants_1.EXTENSION_LAYER_KEY, region, settings);
383
+ expect(layerArn).toEqual(`arn:aws-us-gov:lambda:${region}:${constants_1.GOVCLOUD_LAYER_AWS_ACCOUNT}:layer:Datadog-Extension`);
384
+ }));
385
+ test('gets us-gov-1 gov cloud arm64 Lambda Extension layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
386
+ const config = {
387
+ Architectures: ['arm64'],
388
+ };
389
+ const settings = {
390
+ flushMetricsToLogs: false,
391
+ layerAWSAccount: fixtures_1.mockAwsAccount,
392
+ mergeXrayTraces: false,
393
+ tracingEnabled: false,
394
+ };
395
+ const region = 'us-gov-1';
396
+ const layerArn = commons_1.getLayerArn(config, constants_1.EXTENSION_LAYER_KEY, region, settings);
397
+ expect(layerArn).toEqual(`arn:aws-us-gov:lambda:${region}:${constants_1.GOVCLOUD_LAYER_AWS_ACCOUNT}:layer:Datadog-Extension-ARM`);
398
+ }));
399
+ test('gets sa-east-1 Node12 Lambda Library layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
400
+ const runtime = 'nodejs12.x';
401
+ const config = {
402
+ Runtime: runtime,
403
+ };
404
+ const settings = {
405
+ flushMetricsToLogs: false,
406
+ layerAWSAccount: fixtures_1.mockAwsAccount,
407
+ mergeXrayTraces: false,
408
+ tracingEnabled: false,
409
+ };
410
+ const region = 'sa-east-1';
411
+ const layerArn = commons_1.getLayerArn(config, config.Runtime, region, settings);
412
+ expect(layerArn).toEqual(`arn:aws:lambda:${region}:${fixtures_1.mockAwsAccount}:layer:Datadog-Node12-x`);
413
+ }));
414
+ test('gets sa-east-1 Python3.9 arm64 Lambda Library layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
415
+ const runtime = 'python3.9';
416
+ const config = {
417
+ Architectures: ['arm64'],
418
+ Runtime: runtime,
419
+ };
420
+ const settings = {
421
+ flushMetricsToLogs: false,
422
+ layerAWSAccount: fixtures_1.mockAwsAccount,
423
+ mergeXrayTraces: false,
424
+ tracingEnabled: false,
425
+ };
426
+ const region = 'sa-east-1';
427
+ const layerArn = commons_1.getLayerArn(config, config.Runtime, region, settings);
428
+ expect(layerArn).toEqual(`arn:aws:lambda:${region}:${fixtures_1.mockAwsAccount}:layer:Datadog-Python39-ARM`);
429
+ }));
430
+ test('gets us-gov-1 Python37 gov cloud Lambda Library layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
431
+ const runtime = 'python3.7';
432
+ const config = {
433
+ Runtime: runtime,
434
+ };
435
+ const settings = {
436
+ flushMetricsToLogs: false,
437
+ layerAWSAccount: fixtures_1.mockAwsAccount,
438
+ mergeXrayTraces: false,
439
+ tracingEnabled: false,
440
+ };
441
+ const region = 'us-gov-1';
442
+ const layerArn = commons_1.getLayerArn(config, config.Runtime, region, settings);
443
+ expect(layerArn).toEqual(`arn:aws-us-gov:lambda:${region}:${constants_1.GOVCLOUD_LAYER_AWS_ACCOUNT}:layer:Datadog-Python37`);
444
+ }));
445
+ test('gets us-gov-1 Python39 gov cloud arm64 Lambda Library layer ARN', () => __awaiter(void 0, void 0, void 0, function* () {
446
+ const runtime = 'python3.9';
447
+ const config = {
448
+ Architectures: ['arm64'],
449
+ Runtime: runtime,
450
+ };
451
+ const settings = {
452
+ flushMetricsToLogs: false,
453
+ layerAWSAccount: fixtures_1.mockAwsAccount,
454
+ mergeXrayTraces: false,
455
+ tracingEnabled: false,
456
+ };
457
+ const region = 'us-gov-1';
458
+ const layerArn = commons_1.getLayerArn(config, config.Runtime, region, settings);
459
+ expect(layerArn).toEqual(`arn:aws-us-gov:lambda:${region}:${constants_1.GOVCLOUD_LAYER_AWS_ACCOUNT}:layer:Datadog-Python39-ARM`);
460
+ }));
461
+ });
462
+ describe('getLayerNameWithVersion', () => {
463
+ const OLD_ENV = process.env;
464
+ beforeEach(() => {
465
+ jest.resetModules();
466
+ process.env = {};
467
+ });
468
+ afterAll(() => {
469
+ process.env = OLD_ENV;
470
+ });
471
+ test('returns the correct name and version given an extension layer arn', () => {
472
+ const layerName = constants_1.DD_LAMBDA_EXTENSION_LAYER_NAME;
473
+ const version = '16';
474
+ const layerNameWithVersion = `${layerName}:${version}`;
475
+ const layerArn = `arn:aws:lambda:sa-east-1:${fixtures_1.mockAwsAccount}:layer:${layerNameWithVersion}`;
476
+ expect(commons_1.getLayerNameWithVersion(layerArn)).toBe(layerNameWithVersion);
477
+ });
478
+ test('returns the correct name and version given a library layer arn', () => {
479
+ const layerName = 'Datadog-Python39';
480
+ const version = '59';
481
+ const layerNameWithVersion = `${layerName}:${version}`;
482
+ const layerArn = `arn:aws:lambda:sa-east-1:${fixtures_1.mockAwsAccount}:layer:${layerNameWithVersion}`;
483
+ expect(commons_1.getLayerNameWithVersion(layerArn)).toBe(layerNameWithVersion);
484
+ });
485
+ test('returns undefined if arn is incomplete', () => {
486
+ const layerArn = `arn:aws:lambda:sa-east-1:${fixtures_1.mockAwsAccount}:layer:Datadog-Python39`;
487
+ expect(commons_1.getLayerNameWithVersion(layerArn)).toBe(undefined);
488
+ });
489
+ });
90
490
  describe('getRegion', () => {
91
491
  test('should return the expected region', () => {
92
492
  const functionARN = 'arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world';