@datadog/datadog-ci 0.17.8 → 0.17.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/lambda/__tests__/fixtures.d.ts +42 -0
- package/dist/commands/lambda/__tests__/fixtures.js +73 -0
- package/dist/commands/lambda/__tests__/{function.test.d.ts → functions/commons.test.d.ts} +0 -0
- package/dist/commands/lambda/__tests__/functions/commons.test.js +171 -0
- package/dist/commands/lambda/__tests__/functions/instrument.test.d.ts +1 -0
- package/dist/commands/lambda/__tests__/{function.test.js → functions/instrument.test.js} +355 -417
- package/dist/commands/lambda/__tests__/functions/uninstrument.test.d.ts +1 -0
- package/dist/commands/lambda/__tests__/functions/uninstrument.test.js +298 -0
- package/dist/commands/lambda/__tests__/instrument.test.js +270 -163
- package/dist/commands/lambda/__tests__/loggroup.test.js +98 -34
- package/dist/commands/lambda/__tests__/tags.test.js +107 -31
- package/dist/commands/lambda/__tests__/uninstrument.test.d.ts +1 -0
- package/dist/commands/lambda/__tests__/uninstrument.test.js +223 -0
- package/dist/commands/lambda/constants.d.ts +1 -0
- package/dist/commands/lambda/constants.js +2 -1
- package/dist/commands/lambda/functions/commons.d.ts +71 -0
- package/dist/commands/lambda/functions/commons.js +170 -0
- package/dist/commands/lambda/functions/instrument.d.ts +16 -0
- package/dist/commands/lambda/{function.js → functions/instrument.js} +42 -102
- package/dist/commands/lambda/functions/uninstrument.d.ts +6 -0
- package/dist/commands/lambda/functions/uninstrument.js +110 -0
- package/dist/commands/lambda/index.js +2 -1
- package/dist/commands/lambda/instrument.d.ts +4 -3
- package/dist/commands/lambda/instrument.js +85 -40
- package/dist/commands/lambda/interfaces.d.ts +54 -0
- package/dist/commands/lambda/loggroup.d.ts +4 -7
- package/dist/commands/lambda/loggroup.js +27 -4
- package/dist/commands/lambda/tags.d.ts +3 -4
- package/dist/commands/lambda/tags.js +19 -3
- package/dist/commands/lambda/uninstrument.d.ts +11 -0
- package/dist/commands/lambda/uninstrument.js +127 -0
- package/dist/helpers/__tests__/ci.test.js +23 -0
- package/dist/helpers/ci.js +13 -6
- package/package.json +1 -1
- package/dist/commands/lambda/function.d.ts +0 -43
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
// tslint:disable: no-string-literal
|
|
32
|
+
jest.mock('fs');
|
|
33
|
+
jest.mock('aws-sdk');
|
|
34
|
+
const aws_sdk_1 = require("aws-sdk");
|
|
35
|
+
const chalk_1 = require("chalk");
|
|
36
|
+
const fs = __importStar(require("fs"));
|
|
37
|
+
const constants_1 = require("../constants");
|
|
38
|
+
const uninstrument_1 = require("../uninstrument");
|
|
39
|
+
const fixtures_1 = require("./fixtures");
|
|
40
|
+
describe('uninstrument', () => {
|
|
41
|
+
describe('execute', () => {
|
|
42
|
+
const OLD_ENV = process.env;
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
jest.resetModules();
|
|
45
|
+
process.env = {};
|
|
46
|
+
});
|
|
47
|
+
afterAll(() => {
|
|
48
|
+
process.env = OLD_ENV;
|
|
49
|
+
});
|
|
50
|
+
test('prints dry run data for a valid uninstrumentation', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
;
|
|
52
|
+
fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
|
|
53
|
+
aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({
|
|
54
|
+
'arn:aws:lambda:us-east-1:000000000000:function:uninstrument': {
|
|
55
|
+
Environment: {
|
|
56
|
+
Variables: {
|
|
57
|
+
[constants_1.ENVIRONMENT_ENV_VAR]: 'staging',
|
|
58
|
+
[constants_1.FLUSH_TO_LOG_ENV_VAR]: 'true',
|
|
59
|
+
[constants_1.LAMBDA_HANDLER_ENV_VAR]: 'lambda_function.lambda_handler',
|
|
60
|
+
[constants_1.LOG_LEVEL_ENV_VAR]: 'debug',
|
|
61
|
+
[constants_1.MERGE_XRAY_TRACES_ENV_VAR]: 'false',
|
|
62
|
+
[constants_1.SERVICE_ENV_VAR]: 'middletier',
|
|
63
|
+
[constants_1.SITE_ENV_VAR]: 'datadoghq.com',
|
|
64
|
+
[constants_1.TRACE_ENABLED_ENV_VAR]: 'true',
|
|
65
|
+
[constants_1.VERSION_ENV_VAR]: '0.2',
|
|
66
|
+
USER_VARIABLE: 'shouldnt be deleted by uninstrumentation',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
FunctionArn: 'arn:aws:lambda:us-east-1:000000000000:function:uninstrument',
|
|
70
|
+
Handler: 'datadog_lambda.handler.handler',
|
|
71
|
+
Layers: [
|
|
72
|
+
{
|
|
73
|
+
Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Extension:11',
|
|
74
|
+
CodeSize: 0,
|
|
75
|
+
SigningJobArn: 'some-signing-job-arn',
|
|
76
|
+
SigningProfileVersionArn: 'some-signing-profile',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Python38:49',
|
|
80
|
+
CodeSize: 0,
|
|
81
|
+
SigningJobArn: 'some-signing-job-arn',
|
|
82
|
+
SigningProfileVersionArn: 'some-signing-profile',
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
Runtime: 'python3.8',
|
|
86
|
+
},
|
|
87
|
+
}));
|
|
88
|
+
const cli = fixtures_1.makeCli();
|
|
89
|
+
const context = fixtures_1.createMockContext();
|
|
90
|
+
const functionARN = 'arn:aws:lambda:us-east-1:000000000000:function:uninstrument';
|
|
91
|
+
process.env.DATADOG_API_KEY = '1234';
|
|
92
|
+
const code = yield cli.run(['lambda', 'uninstrument', '-f', functionARN, '-r', 'us-east-1', '-d'], context);
|
|
93
|
+
const output = context.stdout.toString();
|
|
94
|
+
expect(code).toBe(0);
|
|
95
|
+
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
|
+
`);
|
|
110
|
+
}));
|
|
111
|
+
test('runs function update command for valid uninstrumentation', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
112
|
+
;
|
|
113
|
+
fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
|
|
114
|
+
const lambda = fixtures_1.makeMockLambda({
|
|
115
|
+
'arn:aws:lambda:us-east-1:000000000000:function:uninstrument': {
|
|
116
|
+
Environment: {
|
|
117
|
+
Variables: {
|
|
118
|
+
[constants_1.ENVIRONMENT_ENV_VAR]: 'staging',
|
|
119
|
+
[constants_1.FLUSH_TO_LOG_ENV_VAR]: 'true',
|
|
120
|
+
[constants_1.LAMBDA_HANDLER_ENV_VAR]: 'lambda_function.lambda_handler',
|
|
121
|
+
[constants_1.LOG_LEVEL_ENV_VAR]: 'debug',
|
|
122
|
+
[constants_1.MERGE_XRAY_TRACES_ENV_VAR]: 'false',
|
|
123
|
+
[constants_1.SERVICE_ENV_VAR]: 'middletier',
|
|
124
|
+
[constants_1.SITE_ENV_VAR]: 'datadoghq.com',
|
|
125
|
+
[constants_1.TRACE_ENABLED_ENV_VAR]: 'true',
|
|
126
|
+
[constants_1.VERSION_ENV_VAR]: '0.2',
|
|
127
|
+
USER_VARIABLE: 'shouldnt be deleted by uninstrumentation',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
FunctionArn: 'arn:aws:lambda:us-east-1:000000000000:function:uninstrument',
|
|
131
|
+
Handler: 'datadog_lambda.handler.handler',
|
|
132
|
+
Layers: [
|
|
133
|
+
{
|
|
134
|
+
Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Extension:11',
|
|
135
|
+
CodeSize: 0,
|
|
136
|
+
SigningJobArn: 'some-signing-job-arn',
|
|
137
|
+
SigningProfileVersionArn: 'some-signing-profile',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
Arn: 'arn:aws:lambda:sa-east-1:000000000000:layer:Datadog-Python38:49',
|
|
141
|
+
CodeSize: 0,
|
|
142
|
+
SigningJobArn: 'some-signing-job-arn',
|
|
143
|
+
SigningProfileVersionArn: 'some-signing-profile',
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
Runtime: 'python3.8',
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
aws_sdk_1.Lambda.mockImplementation(() => lambda);
|
|
150
|
+
const cli = fixtures_1.makeCli();
|
|
151
|
+
const context = fixtures_1.createMockContext();
|
|
152
|
+
const functionARN = 'arn:aws:lambda:us-east-1:000000000000:function:uninstrument';
|
|
153
|
+
process.env.DATADOG_API_KEY = '1234';
|
|
154
|
+
yield cli.run(['lambda', 'uninstrument', '-f', functionARN, '-r', 'us-east-1'], context);
|
|
155
|
+
expect(lambda.updateFunctionConfiguration).toHaveBeenCalled();
|
|
156
|
+
}));
|
|
157
|
+
test('aborts early when the aws-sdk throws an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
158
|
+
;
|
|
159
|
+
fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
|
|
160
|
+
aws_sdk_1.Lambda.mockImplementation(() => ({
|
|
161
|
+
getFunction: jest.fn().mockImplementation(() => ({ promise: () => Promise.reject('Lambda failed') })),
|
|
162
|
+
}));
|
|
163
|
+
process.env = {};
|
|
164
|
+
const command = fixtures_1.createCommand(uninstrument_1.UninstrumentCommand);
|
|
165
|
+
command['functions'] = ['my-func'];
|
|
166
|
+
command['region'] = 'us-east-1';
|
|
167
|
+
const code = yield command['execute']();
|
|
168
|
+
const output = command.context.stdout.toString();
|
|
169
|
+
expect(code).toBe(1);
|
|
170
|
+
expect(output).toMatch(`${chalk_1.red('[Error]')} Couldn't fetch lambda functions. Lambda failed\n`);
|
|
171
|
+
}));
|
|
172
|
+
test("aborts early when function regions can't be found", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
173
|
+
;
|
|
174
|
+
fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
|
|
175
|
+
aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({}));
|
|
176
|
+
const cli = fixtures_1.makeCli();
|
|
177
|
+
const context = fixtures_1.createMockContext();
|
|
178
|
+
const code = yield cli.run(['lambda', 'uninstrument', '--function', 'my-func'], context);
|
|
179
|
+
const output = context.stdout.toString();
|
|
180
|
+
expect(code).toBe(1);
|
|
181
|
+
expect(output).toMatch('No default region specified for ["my-func"]. Use -r, --region, or use a full functionARN');
|
|
182
|
+
}));
|
|
183
|
+
test('aborts early when no functions are specified', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
184
|
+
;
|
|
185
|
+
fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
|
|
186
|
+
aws_sdk_1.Lambda.mockImplementation(() => fixtures_1.makeMockLambda({}));
|
|
187
|
+
const cli = fixtures_1.makeCli();
|
|
188
|
+
const context = fixtures_1.createMockContext();
|
|
189
|
+
const code = yield cli.run(['lambda', 'uninstrument'], context);
|
|
190
|
+
const output = context.stdout.toString();
|
|
191
|
+
expect(code).toBe(1);
|
|
192
|
+
expect(output).toMatchInlineSnapshot(`
|
|
193
|
+
"No functions specified for un-instrumentation.
|
|
194
|
+
"
|
|
195
|
+
`);
|
|
196
|
+
}));
|
|
197
|
+
test('aborts early when no functions are specified while using config file', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
198
|
+
;
|
|
199
|
+
fs.readFile.mockImplementation((a, b, callback) => callback({}));
|
|
200
|
+
process.env = {};
|
|
201
|
+
const command = fixtures_1.createCommand(uninstrument_1.UninstrumentCommand);
|
|
202
|
+
command['config']['region'] = 'ap-southeast-1';
|
|
203
|
+
yield command['execute']();
|
|
204
|
+
const output = command.context.stdout.toString();
|
|
205
|
+
expect(output).toMatchInlineSnapshot(`
|
|
206
|
+
"No functions specified for un-instrumentation.
|
|
207
|
+
"
|
|
208
|
+
`);
|
|
209
|
+
}));
|
|
210
|
+
});
|
|
211
|
+
describe('printPlannedActions', () => {
|
|
212
|
+
test('prints no output when list is empty', () => {
|
|
213
|
+
process.env = {};
|
|
214
|
+
const command = fixtures_1.createCommand(uninstrument_1.UninstrumentCommand);
|
|
215
|
+
command['printPlannedActions']([]);
|
|
216
|
+
const output = command.context.stdout.toString();
|
|
217
|
+
expect(output).toMatchInlineSnapshot(`
|
|
218
|
+
"No updates will be applied
|
|
219
|
+
"
|
|
220
|
+
`);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
});
|
|
@@ -40,4 +40,5 @@ export declare const CI_SITE_ENV_VAR = "DATADOG_SITE";
|
|
|
40
40
|
export declare const CI_API_KEY_ENV_VAR = "DATADOG_API_KEY";
|
|
41
41
|
export declare const CI_KMS_API_KEY_ENV_VAR = "DATADOG_KMS_API_KEY";
|
|
42
42
|
export declare const LIST_FUNCTIONS_MAX_RETRY_COUNT = 2;
|
|
43
|
+
export declare const MAX_LAMBDA_STATE_CHECK_ATTEMPTS = 3;
|
|
43
44
|
export declare const EXTRA_TAGS_REG_EXP: RegExp;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EXTRA_TAGS_REG_EXP = exports.LIST_FUNCTIONS_MAX_RETRY_COUNT = exports.CI_KMS_API_KEY_ENV_VAR = exports.CI_API_KEY_ENV_VAR = exports.CI_SITE_ENV_VAR = exports.EXTRA_TAGS_ENV_VAR = exports.ENVIRONMENT_ENV_VAR = exports.VERSION_ENV_VAR = exports.SERVICE_ENV_VAR = exports.LAMBDA_HANDLER_ENV_VAR = exports.LOG_LEVEL_ENV_VAR = exports.FLUSH_TO_LOG_ENV_VAR = exports.MERGE_XRAY_TRACES_ENV_VAR = exports.TRACE_ENABLED_ENV_VAR = exports.SITE_ENV_VAR = exports.KMS_API_KEY_ENV_VAR = exports.API_KEY_ENV_VAR = exports.DD_LAMBDA_EXTENSION_LAYER_NAME = exports.TAG_VERSION_NAME = exports.SUBSCRIPTION_FILTER_NAME = exports.GOVCLOUD_LAYER_AWS_ACCOUNT = exports.DEFAULT_LAYER_AWS_ACCOUNT = exports.HANDLER_LOCATION = exports.RUNTIME_LAYER_LOOKUP = void 0;
|
|
3
|
+
exports.EXTRA_TAGS_REG_EXP = exports.MAX_LAMBDA_STATE_CHECK_ATTEMPTS = exports.LIST_FUNCTIONS_MAX_RETRY_COUNT = exports.CI_KMS_API_KEY_ENV_VAR = exports.CI_API_KEY_ENV_VAR = exports.CI_SITE_ENV_VAR = exports.EXTRA_TAGS_ENV_VAR = exports.ENVIRONMENT_ENV_VAR = exports.VERSION_ENV_VAR = exports.SERVICE_ENV_VAR = exports.LAMBDA_HANDLER_ENV_VAR = exports.LOG_LEVEL_ENV_VAR = exports.FLUSH_TO_LOG_ENV_VAR = exports.MERGE_XRAY_TRACES_ENV_VAR = exports.TRACE_ENABLED_ENV_VAR = exports.SITE_ENV_VAR = exports.KMS_API_KEY_ENV_VAR = exports.API_KEY_ENV_VAR = exports.DD_LAMBDA_EXTENSION_LAYER_NAME = exports.TAG_VERSION_NAME = exports.SUBSCRIPTION_FILTER_NAME = exports.GOVCLOUD_LAYER_AWS_ACCOUNT = exports.DEFAULT_LAYER_AWS_ACCOUNT = exports.HANDLER_LOCATION = exports.RUNTIME_LAYER_LOOKUP = void 0;
|
|
4
4
|
exports.RUNTIME_LAYER_LOOKUP = {
|
|
5
5
|
'nodejs10.x': 'Datadog-Node10-x',
|
|
6
6
|
'nodejs12.x': 'Datadog-Node12-x',
|
|
@@ -46,6 +46,7 @@ exports.CI_SITE_ENV_VAR = 'DATADOG_SITE';
|
|
|
46
46
|
exports.CI_API_KEY_ENV_VAR = 'DATADOG_API_KEY';
|
|
47
47
|
exports.CI_KMS_API_KEY_ENV_VAR = 'DATADOG_KMS_API_KEY';
|
|
48
48
|
exports.LIST_FUNCTIONS_MAX_RETRY_COUNT = 2;
|
|
49
|
+
exports.MAX_LAMBDA_STATE_CHECK_ATTEMPTS = 3;
|
|
49
50
|
// DD_TAGS Regular Expression
|
|
50
51
|
// This RegExp ensures that the --extra-tags string
|
|
51
52
|
// matches a list of <key>:<value> separated by commas
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { CloudWatchLogs, Lambda } from 'aws-sdk';
|
|
2
|
+
import { FunctionConfiguration } from '../interfaces';
|
|
3
|
+
/**
|
|
4
|
+
* Returns an array of merged layer ARNs if given a Full Layer ARN,
|
|
5
|
+
* if not, it justs returns the layer ARNs provided.
|
|
6
|
+
*
|
|
7
|
+
* @param fullLayerARN a complete layer ARN.
|
|
8
|
+
* @param partialLayerARN a partial layer ARN.
|
|
9
|
+
* @param layerARNs an array of layer ARNs.
|
|
10
|
+
* @returns an array of layer ARNs.
|
|
11
|
+
*/
|
|
12
|
+
export declare const addLayerARN: (fullLayerARN: string | undefined, partialLayerARN: string, layerARNs: string[]) => string[];
|
|
13
|
+
/**
|
|
14
|
+
* Returns an arrayed grouped functions by its region, it
|
|
15
|
+
* throws an error if there are functions without a region.
|
|
16
|
+
*
|
|
17
|
+
* @param functions an array of strings comprised by
|
|
18
|
+
* Functions ARNs, Partial ARNs, or Function Names.
|
|
19
|
+
* @param defaultRegion a fallback region
|
|
20
|
+
* @returns an array of functions grouped by region
|
|
21
|
+
*/
|
|
22
|
+
export declare const collectFunctionsByRegion: (functions: string[], defaultRegion: string | undefined) => {
|
|
23
|
+
[key: string]: string[];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Given a Lambda instance and an array of Lambda names,
|
|
27
|
+
* return all the Lambda Function Configurations.
|
|
28
|
+
*
|
|
29
|
+
* @param lambda an instance of Lambda from aws-sdk.
|
|
30
|
+
* @param functionARNs an array of strings comprised by
|
|
31
|
+
* Functions ARNs, Partial ARNs, or Function Names.
|
|
32
|
+
* @returns an array of Lambda FunctionConfiguration's.
|
|
33
|
+
*/
|
|
34
|
+
export declare const getLambdaFunctionConfigs: (lambda: Lambda, functionARNs: string[]) => Promise<Lambda.FunctionConfiguration[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Call the aws-sdk Lambda api to get a Function given
|
|
37
|
+
* an ARN and then return its Configuration.
|
|
38
|
+
*
|
|
39
|
+
* @param lambda an instance of Lambda from aws-sdk.
|
|
40
|
+
* @param functionARN a string, can be Function ARN, Partial ARN, or a Function Name.
|
|
41
|
+
* @returns the Lambda FunctionConfiguration of the given ARN.
|
|
42
|
+
*/
|
|
43
|
+
export declare const getLambdaFunctionConfig: (lambda: Lambda, functionARN: string) => Promise<Lambda.FunctionConfiguration>;
|
|
44
|
+
/**
|
|
45
|
+
* Given a Function ARN, return its region by splitting the string,
|
|
46
|
+
* can return undefined if it is doesn't exist.
|
|
47
|
+
*
|
|
48
|
+
* @param functionARN a string, can be Function ARN, Partial ARN, or a Function Name.
|
|
49
|
+
* @returns the region of an ARN.
|
|
50
|
+
*/
|
|
51
|
+
export declare const getRegion: (functionARN: string) => string | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Returns whether a Lambda Function is active or throws an error if
|
|
54
|
+
* the FunctionConfiguration does not comply with `Successful` or `Active`.
|
|
55
|
+
*
|
|
56
|
+
* @param lambda an instance of Lambda from aws-sdk.
|
|
57
|
+
* @param config a Lambda FunctionConfiguration.
|
|
58
|
+
* @param functionArn a string, can be Function ARN, Partial ARN, or a Function Name.
|
|
59
|
+
* @param attempts the number of attemps that have passed since the last retry.
|
|
60
|
+
* @returns if a Lambda Function is active.
|
|
61
|
+
*/
|
|
62
|
+
export declare const isLambdaActive: (lambda: Lambda, config: Lambda.FunctionConfiguration, functionArn: string, attempts?: number) => Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* Returns whether the runtime given is supported by the Datadog CI Lambda.
|
|
65
|
+
*
|
|
66
|
+
* @param runtime a string representing a Lambda FunctionConfiguration Runtime.
|
|
67
|
+
* @returns if a runtime is supported.
|
|
68
|
+
*/
|
|
69
|
+
export declare const isSupportedRuntime: (runtime?: string | undefined) => runtime is "nodejs10.x" | "nodejs12.x" | "nodejs14.x" | "python2.7" | "python3.6" | "python3.7" | "python3.8" | "python3.9";
|
|
70
|
+
export declare const sentenceMatchesRegEx: (sentence: string, regex: RegExp) => RegExpMatchArray | null;
|
|
71
|
+
export declare const updateLambdaFunctionConfigs: (lambda: Lambda, cloudWatch: CloudWatchLogs, configs: FunctionConfiguration[]) => Promise<void>;
|
|
@@ -0,0 +1,170 @@
|
|
|
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
|
+
exports.updateLambdaFunctionConfigs = exports.sentenceMatchesRegEx = exports.isSupportedRuntime = exports.isLambdaActive = exports.getRegion = exports.getLambdaFunctionConfig = exports.getLambdaFunctionConfigs = exports.collectFunctionsByRegion = exports.addLayerARN = void 0;
|
|
13
|
+
const constants_1 = require("../constants");
|
|
14
|
+
const loggroup_1 = require("../loggroup");
|
|
15
|
+
const tags_1 = require("../tags");
|
|
16
|
+
/**
|
|
17
|
+
* Returns an array of merged layer ARNs if given a Full Layer ARN,
|
|
18
|
+
* if not, it justs returns the layer ARNs provided.
|
|
19
|
+
*
|
|
20
|
+
* @param fullLayerARN a complete layer ARN.
|
|
21
|
+
* @param partialLayerARN a partial layer ARN.
|
|
22
|
+
* @param layerARNs an array of layer ARNs.
|
|
23
|
+
* @returns an array of layer ARNs.
|
|
24
|
+
*/
|
|
25
|
+
const addLayerARN = (fullLayerARN, partialLayerARN, layerARNs) => {
|
|
26
|
+
if (fullLayerARN) {
|
|
27
|
+
if (!layerARNs.includes(fullLayerARN)) {
|
|
28
|
+
// Remove any other versions of the layer
|
|
29
|
+
layerARNs = [...layerARNs.filter((l) => !l.startsWith(partialLayerARN)), fullLayerARN];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return layerARNs;
|
|
33
|
+
};
|
|
34
|
+
exports.addLayerARN = addLayerARN;
|
|
35
|
+
/**
|
|
36
|
+
* Returns an arrayed grouped functions by its region, it
|
|
37
|
+
* throws an error if there are functions without a region.
|
|
38
|
+
*
|
|
39
|
+
* @param functions an array of strings comprised by
|
|
40
|
+
* Functions ARNs, Partial ARNs, or Function Names.
|
|
41
|
+
* @param defaultRegion a fallback region
|
|
42
|
+
* @returns an array of functions grouped by region
|
|
43
|
+
*/
|
|
44
|
+
const collectFunctionsByRegion = (functions, defaultRegion) => {
|
|
45
|
+
var _a;
|
|
46
|
+
const groups = {};
|
|
47
|
+
const regionless = [];
|
|
48
|
+
for (const func of functions) {
|
|
49
|
+
const region = (_a = exports.getRegion(func)) !== null && _a !== void 0 ? _a : defaultRegion;
|
|
50
|
+
if (region === undefined) {
|
|
51
|
+
regionless.push(func);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (groups[region] === undefined) {
|
|
55
|
+
groups[region] = [];
|
|
56
|
+
}
|
|
57
|
+
const group = groups[region];
|
|
58
|
+
group.push(func);
|
|
59
|
+
}
|
|
60
|
+
if (regionless.length > 0) {
|
|
61
|
+
throw Error(`No default region specified for ${JSON.stringify(regionless)}. Use -r, --region, or use a full functionARN\n`);
|
|
62
|
+
}
|
|
63
|
+
return groups;
|
|
64
|
+
};
|
|
65
|
+
exports.collectFunctionsByRegion = collectFunctionsByRegion;
|
|
66
|
+
/**
|
|
67
|
+
* Given a Lambda instance and an array of Lambda names,
|
|
68
|
+
* return all the Lambda Function Configurations.
|
|
69
|
+
*
|
|
70
|
+
* @param lambda an instance of Lambda from aws-sdk.
|
|
71
|
+
* @param functionARNs an array of strings comprised by
|
|
72
|
+
* Functions ARNs, Partial ARNs, or Function Names.
|
|
73
|
+
* @returns an array of Lambda FunctionConfiguration's.
|
|
74
|
+
*/
|
|
75
|
+
const getLambdaFunctionConfigs = (lambda, functionARNs) => {
|
|
76
|
+
const promises = functionARNs.map((fn) => exports.getLambdaFunctionConfig(lambda, fn));
|
|
77
|
+
return Promise.all(promises);
|
|
78
|
+
};
|
|
79
|
+
exports.getLambdaFunctionConfigs = getLambdaFunctionConfigs;
|
|
80
|
+
/**
|
|
81
|
+
* Call the aws-sdk Lambda api to get a Function given
|
|
82
|
+
* an ARN and then return its Configuration.
|
|
83
|
+
*
|
|
84
|
+
* @param lambda an instance of Lambda from aws-sdk.
|
|
85
|
+
* @param functionARN a string, can be Function ARN, Partial ARN, or a Function Name.
|
|
86
|
+
* @returns the Lambda FunctionConfiguration of the given ARN.
|
|
87
|
+
*/
|
|
88
|
+
const getLambdaFunctionConfig = (lambda, functionARN) => __awaiter(void 0, void 0, void 0, function* () {
|
|
89
|
+
const params = {
|
|
90
|
+
FunctionName: functionARN,
|
|
91
|
+
};
|
|
92
|
+
const result = yield lambda.getFunction(params).promise();
|
|
93
|
+
// AWS typescript API is slightly mistyped, adds undefineds where
|
|
94
|
+
// there shouldn't be.
|
|
95
|
+
const config = result.Configuration;
|
|
96
|
+
return config;
|
|
97
|
+
});
|
|
98
|
+
exports.getLambdaFunctionConfig = getLambdaFunctionConfig;
|
|
99
|
+
/**
|
|
100
|
+
* Given a Function ARN, return its region by splitting the string,
|
|
101
|
+
* can return undefined if it is doesn't exist.
|
|
102
|
+
*
|
|
103
|
+
* @param functionARN a string, can be Function ARN, Partial ARN, or a Function Name.
|
|
104
|
+
* @returns the region of an ARN.
|
|
105
|
+
*/
|
|
106
|
+
const getRegion = (functionARN) => {
|
|
107
|
+
const [, , , region] = functionARN.split(':');
|
|
108
|
+
return region === undefined || region === '*' ? undefined : region;
|
|
109
|
+
};
|
|
110
|
+
exports.getRegion = getRegion;
|
|
111
|
+
/**
|
|
112
|
+
* Returns whether a Lambda Function is active or throws an error if
|
|
113
|
+
* the FunctionConfiguration does not comply with `Successful` or `Active`.
|
|
114
|
+
*
|
|
115
|
+
* @param lambda an instance of Lambda from aws-sdk.
|
|
116
|
+
* @param config a Lambda FunctionConfiguration.
|
|
117
|
+
* @param functionArn a string, can be Function ARN, Partial ARN, or a Function Name.
|
|
118
|
+
* @param attempts the number of attemps that have passed since the last retry.
|
|
119
|
+
* @returns if a Lambda Function is active.
|
|
120
|
+
*/
|
|
121
|
+
const isLambdaActive = (lambda, config, functionArn, attempts = 0) => __awaiter(void 0, void 0, void 0, function* () {
|
|
122
|
+
// TODO remove 1 Oct 2021 https://aws.amazon.com/blogs/compute/tracking-the-state-of-lambda-functions/
|
|
123
|
+
if (!config.State || !config.LastUpdateStatus) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
if (config.LastUpdateStatus === 'Successful' && config.State === 'Active') {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
if (config.State === 'Pending' && attempts <= constants_1.MAX_LAMBDA_STATE_CHECK_ATTEMPTS) {
|
|
130
|
+
yield wait(Math.pow(2, attempts) * 1000);
|
|
131
|
+
const refetchedConfig = yield exports.getLambdaFunctionConfig(lambda, functionArn);
|
|
132
|
+
return exports.isLambdaActive(lambda, refetchedConfig, functionArn, (attempts += 1));
|
|
133
|
+
}
|
|
134
|
+
throw Error(`Can't instrument ${functionArn}, as current State is ${config.State} (must be "Active") and Last Update Status is ${config.LastUpdateStatus} (must be "Successful")`);
|
|
135
|
+
});
|
|
136
|
+
exports.isLambdaActive = isLambdaActive;
|
|
137
|
+
/**
|
|
138
|
+
* Returns whether the runtime given is supported by the Datadog CI Lambda.
|
|
139
|
+
*
|
|
140
|
+
* @param runtime a string representing a Lambda FunctionConfiguration Runtime.
|
|
141
|
+
* @returns if a runtime is supported.
|
|
142
|
+
*/
|
|
143
|
+
const isSupportedRuntime = (runtime) => {
|
|
144
|
+
const lookup = constants_1.RUNTIME_LAYER_LOOKUP;
|
|
145
|
+
return runtime !== undefined && lookup[runtime] !== undefined;
|
|
146
|
+
};
|
|
147
|
+
exports.isSupportedRuntime = isSupportedRuntime;
|
|
148
|
+
const sentenceMatchesRegEx = (sentence, regex) => sentence.match(regex);
|
|
149
|
+
exports.sentenceMatchesRegEx = sentenceMatchesRegEx;
|
|
150
|
+
const updateLambdaFunctionConfigs = (lambda, cloudWatch, configs) => __awaiter(void 0, void 0, void 0, function* () {
|
|
151
|
+
const results = configs.map((c) => __awaiter(void 0, void 0, void 0, function* () {
|
|
152
|
+
if (c.updateRequest !== undefined) {
|
|
153
|
+
yield lambda.updateFunctionConfiguration(c.updateRequest).promise();
|
|
154
|
+
}
|
|
155
|
+
if (c.logGroupConfiguration !== undefined) {
|
|
156
|
+
yield loggroup_1.applyLogGroupConfig(cloudWatch, c.logGroupConfiguration);
|
|
157
|
+
}
|
|
158
|
+
if (c.tagConfiguration !== undefined) {
|
|
159
|
+
yield tags_1.applyTagConfig(lambda, c.tagConfiguration);
|
|
160
|
+
}
|
|
161
|
+
}));
|
|
162
|
+
yield Promise.all(results);
|
|
163
|
+
});
|
|
164
|
+
exports.updateLambdaFunctionConfigs = updateLambdaFunctionConfigs;
|
|
165
|
+
/**
|
|
166
|
+
* Waits for n ms
|
|
167
|
+
*
|
|
168
|
+
* @param ms
|
|
169
|
+
*/
|
|
170
|
+
const wait = (ms) => new Promise((res) => setTimeout(res, ms));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CloudWatchLogs, Lambda } from 'aws-sdk';
|
|
2
|
+
import { Runtime } from '../constants';
|
|
3
|
+
import { FunctionConfiguration, InstrumentationSettings, LogGroupConfiguration, TagConfiguration } from '../interfaces';
|
|
4
|
+
export declare const getFunctionConfigs: (lambda: Lambda, cloudWatch: CloudWatchLogs, region: string, functionARNs: string[], settings: InstrumentationSettings) => Promise<FunctionConfiguration[]>;
|
|
5
|
+
export declare const getFunctionConfig: (lambda: Lambda, cloudWatch: CloudWatchLogs, config: Lambda.FunctionConfiguration, region: string, settings: InstrumentationSettings) => Promise<{
|
|
6
|
+
functionARN: string;
|
|
7
|
+
lambdaConfig: Lambda.FunctionConfiguration;
|
|
8
|
+
lambdaLibraryLayerArn: string;
|
|
9
|
+
logGroupConfiguration: LogGroupConfiguration | undefined;
|
|
10
|
+
tagConfiguration: TagConfiguration | undefined;
|
|
11
|
+
updateRequest: Lambda.UpdateFunctionConfigurationRequest | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const getLambdaConfigsFromRegEx: (lambda: Lambda, cloudWatch: CloudWatchLogs, region: string, pattern: string, settings: InstrumentationSettings) => Promise<FunctionConfiguration[]>;
|
|
14
|
+
export declare const getLayerArn: (runtime: Runtime, settings: InstrumentationSettings, region: string) => string;
|
|
15
|
+
export declare const getExtensionArn: (settings: InstrumentationSettings, region: string) => string;
|
|
16
|
+
export declare const calculateUpdateRequest: (config: Lambda.FunctionConfiguration, settings: InstrumentationSettings, lambdaLibraryLayerArn: string, lambdaExtensionLayerArn: string, runtime: Runtime) => Lambda.UpdateFunctionConfigurationRequest | undefined;
|