@depup/artillery 2.0.30-depup.0

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 (90) hide show
  1. package/README.md +63 -0
  2. package/bin/run +29 -0
  3. package/bin/run.cmd +3 -0
  4. package/changes.json +138 -0
  5. package/console-reporter.js +1 -0
  6. package/lib/artillery-global.js +33 -0
  7. package/lib/cli/banner.js +8 -0
  8. package/lib/cli/common-flags.js +80 -0
  9. package/lib/cli/hooks/version.js +20 -0
  10. package/lib/cmds/dino.js +109 -0
  11. package/lib/cmds/quick.js +122 -0
  12. package/lib/cmds/report.js +34 -0
  13. package/lib/cmds/run-aci.js +91 -0
  14. package/lib/cmds/run-fargate.js +192 -0
  15. package/lib/cmds/run-lambda.js +96 -0
  16. package/lib/cmds/run.js +671 -0
  17. package/lib/console-capture.js +92 -0
  18. package/lib/console-reporter.js +438 -0
  19. package/lib/create-bom/built-in-plugins.js +12 -0
  20. package/lib/create-bom/create-bom.js +301 -0
  21. package/lib/dispatcher.js +9 -0
  22. package/lib/dist.js +222 -0
  23. package/lib/index.js +5 -0
  24. package/lib/launch-platform.js +439 -0
  25. package/lib/load-plugins.js +113 -0
  26. package/lib/platform/aws/aws-cloudwatch.js +106 -0
  27. package/lib/platform/aws/aws-create-sqs-queue.js +58 -0
  28. package/lib/platform/aws/aws-ensure-s3-bucket-exists.js +78 -0
  29. package/lib/platform/aws/aws-get-account-id.js +26 -0
  30. package/lib/platform/aws/aws-get-bucket-region.js +18 -0
  31. package/lib/platform/aws/aws-get-credentials.js +28 -0
  32. package/lib/platform/aws/aws-get-default-region.js +26 -0
  33. package/lib/platform/aws/aws-whoami.js +15 -0
  34. package/lib/platform/aws/constants.js +7 -0
  35. package/lib/platform/aws/iam-cf-templates/aws-iam-fargate-cf-template.yml +219 -0
  36. package/lib/platform/aws/iam-cf-templates/aws-iam-lambda-cf-template.yml +125 -0
  37. package/lib/platform/aws/iam-cf-templates/gh-oidc-fargate.yml +241 -0
  38. package/lib/platform/aws/iam-cf-templates/gh-oidc-lambda.yml +153 -0
  39. package/lib/platform/aws-ecs/ecs.js +247 -0
  40. package/lib/platform/aws-ecs/legacy/aws-util.js +134 -0
  41. package/lib/platform/aws-ecs/legacy/bom.js +528 -0
  42. package/lib/platform/aws-ecs/legacy/constants.js +27 -0
  43. package/lib/platform/aws-ecs/legacy/create-s3-client.js +24 -0
  44. package/lib/platform/aws-ecs/legacy/create-test.js +247 -0
  45. package/lib/platform/aws-ecs/legacy/errors.js +34 -0
  46. package/lib/platform/aws-ecs/legacy/find-public-subnets.js +149 -0
  47. package/lib/platform/aws-ecs/legacy/plugins/artillery-plugin-inspect-script/index.js +27 -0
  48. package/lib/platform/aws-ecs/legacy/plugins/artillery-plugin-sqs-reporter/azure-aqs.js +80 -0
  49. package/lib/platform/aws-ecs/legacy/plugins/artillery-plugin-sqs-reporter/index.js +202 -0
  50. package/lib/platform/aws-ecs/legacy/plugins.js +16 -0
  51. package/lib/platform/aws-ecs/legacy/run-cluster.js +1994 -0
  52. package/lib/platform/aws-ecs/legacy/sqs-reporter.js +401 -0
  53. package/lib/platform/aws-ecs/legacy/tags.js +22 -0
  54. package/lib/platform/aws-ecs/legacy/test-run-status.js +9 -0
  55. package/lib/platform/aws-ecs/legacy/time.js +67 -0
  56. package/lib/platform/aws-ecs/legacy/util.js +97 -0
  57. package/lib/platform/aws-ecs/worker/Dockerfile +64 -0
  58. package/lib/platform/aws-ecs/worker/helpers.sh +80 -0
  59. package/lib/platform/aws-ecs/worker/loadgen-worker +656 -0
  60. package/lib/platform/aws-lambda/dependencies.js +130 -0
  61. package/lib/platform/aws-lambda/index.js +734 -0
  62. package/lib/platform/aws-lambda/lambda-handler/a9-handler-dependencies.js +73 -0
  63. package/lib/platform/aws-lambda/lambda-handler/a9-handler-helpers.js +43 -0
  64. package/lib/platform/aws-lambda/lambda-handler/a9-handler-index.js +235 -0
  65. package/lib/platform/aws-lambda/lambda-handler/package.json +15 -0
  66. package/lib/platform/aws-lambda/prices.js +29 -0
  67. package/lib/platform/az/aci.js +694 -0
  68. package/lib/platform/az/aqs-queue-consumer.js +88 -0
  69. package/lib/platform/az/regions.js +52 -0
  70. package/lib/platform/cloud/api.js +72 -0
  71. package/lib/platform/cloud/cloud.js +448 -0
  72. package/lib/platform/cloud/http-client.js +19 -0
  73. package/lib/platform/local/artillery-worker-local.js +154 -0
  74. package/lib/platform/local/index.js +174 -0
  75. package/lib/platform/local/worker.js +261 -0
  76. package/lib/platform/worker-states.js +13 -0
  77. package/lib/queue-consumer/index.js +56 -0
  78. package/lib/stash.js +41 -0
  79. package/lib/telemetry.js +78 -0
  80. package/lib/util/await-on-ee.js +24 -0
  81. package/lib/util/generate-id.js +9 -0
  82. package/lib/util/parse-tag-string.js +21 -0
  83. package/lib/util/prepare-test-execution-plan.js +216 -0
  84. package/lib/util/sleep.js +7 -0
  85. package/lib/util/validate-script.js +132 -0
  86. package/lib/util.js +294 -0
  87. package/lib/utils-config.js +31 -0
  88. package/package.json +323 -0
  89. package/types.d.ts +317 -0
  90. package/util.js +1 -0
@@ -0,0 +1,73 @@
1
+ const fs = require('node:fs');
2
+ const path = require('node:path');
3
+ const { runProcess } = require('./a9-handler-helpers');
4
+
5
+ const syncTestData = async (bucketName, testRunId) => {
6
+ console.log('Syncing test data');
7
+ const LOCAL_TEST_DATA_PATH = `/tmp/test_data/${testRunId}`;
8
+ const REMOTE_TEST_DATA_PATH = `s3://${bucketName}/tests/${testRunId}`;
9
+
10
+ if (!fs.existsSync(LOCAL_TEST_DATA_PATH)) {
11
+ fs.mkdirSync(LOCAL_TEST_DATA_PATH, { recursive: true });
12
+ }
13
+
14
+ const result = await runProcess(
15
+ 'aws',
16
+ ['s3', 'sync', REMOTE_TEST_DATA_PATH, LOCAL_TEST_DATA_PATH],
17
+ { log: true }
18
+ );
19
+
20
+ if (result.code !== 0 || result.stderr) {
21
+ throw new Error(`Failed to sync test data:\n ${result.stderr}`);
22
+ }
23
+ console.log('Test data synced');
24
+ };
25
+
26
+ const installNpmDependencies = async (testDataLocation) => {
27
+ //TODO: handle npmrc (i.e. artifactory, etc)
28
+ console.log(`Changing directory to ${testDataLocation}`);
29
+ process.chdir(testDataLocation);
30
+
31
+ const metadataJson = fs.readFileSync(
32
+ path.join(testDataLocation, 'metadata.json')
33
+ );
34
+
35
+ //first, install custom dependencies
36
+ for (const dep of JSON.parse(metadataJson).modules) {
37
+ console.log(`Installing ${dep}`);
38
+ await runProcess('npm', ['install', dep, '--prefix', testDataLocation], {
39
+ log: true,
40
+ env: {
41
+ HOME: testDataLocation
42
+ }
43
+ });
44
+ }
45
+
46
+ if (!fs.existsSync(path.join(testDataLocation, 'package.json'))) {
47
+ await runProcess('npm', ['init', '-y', '--quiet'], {
48
+ log: true,
49
+ env: {
50
+ HOME: testDataLocation
51
+ }
52
+ });
53
+ }
54
+
55
+ const installResult = await runProcess(
56
+ 'npm',
57
+ ['install', '--prefix', testDataLocation],
58
+ {
59
+ log: true,
60
+ env: {
61
+ HOME: testDataLocation
62
+ }
63
+ }
64
+ );
65
+
66
+ console.log(installResult);
67
+ console.log('Finished installing test data');
68
+ };
69
+
70
+ module.exports = {
71
+ syncTestData,
72
+ installNpmDependencies
73
+ };
@@ -0,0 +1,43 @@
1
+ const { spawn } = require('node:child_process');
2
+
3
+ const sleep = async (n) => new Promise((resolve, _reject) => {
4
+ setTimeout(() => {
5
+ resolve();
6
+ }, n);
7
+ });
8
+
9
+ async function runProcess(name, args, { env, log }) {
10
+ return new Promise((resolve, _reject) => {
11
+ const proc = spawn(name, args, { env });
12
+ let stdout = '';
13
+ let stderr = '';
14
+
15
+ proc.stdout.on('data', (data) => {
16
+ if (log) {
17
+ console.log(data.toString());
18
+ }
19
+ stdout += data.toString();
20
+ });
21
+
22
+ proc.stderr.on('data', (data) => {
23
+ if (log) {
24
+ console.error(data.toString());
25
+ }
26
+
27
+ stderr += data.toString();
28
+ });
29
+
30
+ proc.once('close', (code) => {
31
+ resolve({ stdout, stderr, code });
32
+ });
33
+
34
+ proc.on('error', (err) => {
35
+ resolve({ stdout, stderr, err });
36
+ });
37
+ });
38
+ }
39
+
40
+ module.exports = {
41
+ runProcess,
42
+ sleep
43
+ };
@@ -0,0 +1,235 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
+
5
+ const { SQSClient, SendMessageCommand } = require('@aws-sdk/client-sqs');
6
+ const { S3Client, HeadObjectCommand } = require('@aws-sdk/client-s3');
7
+ const { randomUUID } = require('node:crypto');
8
+ const { runProcess, sleep } = require('./a9-handler-helpers');
9
+ const {
10
+ syncTestData,
11
+ installNpmDependencies
12
+ } = require('./a9-handler-dependencies');
13
+ const path = require('node:path');
14
+
15
+ const TIMEOUT_THRESHOLD_MSEC = 20 * 1000;
16
+
17
+ class MQ {
18
+ constructor({ region, queueUrl, attrs }) {
19
+ this.sqs = new SQSClient({ region });
20
+ this.queueUrl = queueUrl;
21
+ this.attrs = attrs;
22
+ }
23
+
24
+ async send(body) {
25
+ const messageAttributes = Object.keys(this.attrs).reduce((acc, key) => {
26
+ acc[key] = {
27
+ DataType: 'String',
28
+ StringValue: this.attrs[key]
29
+ };
30
+ return acc;
31
+ }, {});
32
+
33
+ return this.sqs.send(
34
+ new SendMessageCommand({
35
+ QueueUrl: this.queueUrl,
36
+ MessageBody: JSON.stringify(body),
37
+ MessageAttributes: messageAttributes,
38
+ MessageDeduplicationId: randomUUID(),
39
+ MessageGroupId: this.attrs.testId
40
+ })
41
+ );
42
+ }
43
+ }
44
+
45
+ async function handler(event, context) {
46
+ const {
47
+ SQS_QUEUE_URL,
48
+ SQS_REGION,
49
+ TEST_RUN_ID,
50
+ WORKER_ID,
51
+ ARTILLERY_ARGS,
52
+ BUCKET,
53
+ ENV,
54
+ WAIT_FOR_GREEN,
55
+ ARTILLERY_CLOUD_API_KEY,
56
+ ARTILLERY_CLOUD_ENDPOINT
57
+ } = event;
58
+
59
+ console.log('TEST_RUN_ID: ', TEST_RUN_ID);
60
+
61
+ const mq = new MQ({
62
+ region: SQS_REGION,
63
+ queueUrl: SQS_QUEUE_URL,
64
+ attrs: {
65
+ testId: TEST_RUN_ID,
66
+ workerId: WORKER_ID
67
+ }
68
+ });
69
+
70
+ const TEST_DATA_LOCATION = `/tmp/test_data/${TEST_RUN_ID}`;
71
+
72
+ try {
73
+ await syncTestData(BUCKET, TEST_RUN_ID);
74
+ } catch (err) {
75
+ await mq.send({
76
+ event: 'workerError',
77
+ reason: 'TestDataSyncFailure',
78
+ logs: {
79
+ err: {
80
+ message: err.message,
81
+ stack: err.stack
82
+ }
83
+ }
84
+ });
85
+ }
86
+
87
+ try {
88
+ await installNpmDependencies(TEST_DATA_LOCATION);
89
+ } catch (err) {
90
+ await mq.send({
91
+ event: 'workerError',
92
+ reason: 'InstallDependenciesFailure',
93
+ logs: {
94
+ err: {
95
+ message: err.message,
96
+ stack: err.stack
97
+ }
98
+ }
99
+ });
100
+ }
101
+
102
+ const interval = setInterval(async () => {
103
+ const timeRemaining = context.getRemainingTimeInMillis();
104
+
105
+ if (timeRemaining > TIMEOUT_THRESHOLD_MSEC) {
106
+ return;
107
+ }
108
+
109
+ await mq.send({
110
+ event: 'workerError',
111
+ reason: 'AWSLambdaTimeout'
112
+ });
113
+
114
+ clearInterval(interval);
115
+ }, 5000).unref();
116
+
117
+ // TODO: Stop Artillery process - relying on Lambda runtime to shut everything down now
118
+
119
+ const s3 = new S3Client();
120
+ await mq.send({ event: 'workerReady' });
121
+
122
+ let waitingFor = 0;
123
+ const MAX_WAIT_MSEC = 3 * 60 * 1000;
124
+ const SLEEP_MSEC = 2500;
125
+
126
+ if (WAIT_FOR_GREEN) {
127
+ while (waitingFor < MAX_WAIT_MSEC) {
128
+ try {
129
+ const params = {
130
+ Bucket: BUCKET,
131
+ Key: `/${TEST_RUN_ID}/green`
132
+ };
133
+ await s3.send(new HeadObjectCommand(params));
134
+ break;
135
+ } catch (_err) {
136
+ await sleep(SLEEP_MSEC);
137
+ waitingFor += SLEEP_MSEC;
138
+ }
139
+ }
140
+ }
141
+
142
+ try {
143
+ const { err, code, stdout, stderr } = await execArtillery({
144
+ SQS_QUEUE_URL,
145
+ SQS_REGION,
146
+ TEST_RUN_ID,
147
+ WORKER_ID,
148
+ ARTILLERY_ARGS,
149
+ TEST_DATA_LOCATION,
150
+ ENV,
151
+ ARTILLERY_CLOUD_API_KEY,
152
+ ARTILLERY_CLOUD_ENDPOINT
153
+ });
154
+
155
+ if (err || code !== 0) {
156
+ console.log(err);
157
+ await mq.send({
158
+ event: 'workerError',
159
+ reason: 'ArtilleryError',
160
+ exitCode: code,
161
+ logs: { stdout, stderr }
162
+ });
163
+ }
164
+ } catch (err) {
165
+ console.error(err);
166
+
167
+ await mq.send({
168
+ event: 'workerError',
169
+ reason: 'StartupFailure',
170
+ logs: {
171
+ err: {
172
+ message: err.message,
173
+ stack: err.stack
174
+ }
175
+ }
176
+ });
177
+ }
178
+ }
179
+
180
+ async function execArtillery(options) {
181
+ const {
182
+ SQS_QUEUE_URL,
183
+ SQS_REGION,
184
+ TEST_RUN_ID,
185
+ WORKER_ID,
186
+ ARTILLERY_ARGS,
187
+ ENV,
188
+ NODE_BINARY_PATH,
189
+ ARTILLERY_BINARY_PATH,
190
+ TEST_DATA_LOCATION,
191
+ ARTILLERY_CLOUD_API_KEY,
192
+ ARTILLERY_CLOUD_ENDPOINT
193
+ } = options;
194
+
195
+ const env = Object.assign(
196
+ {},
197
+ process.env,
198
+ {
199
+ ARTILLERY_PLUGINS: `{"sqs-reporter":{"region": "${SQS_REGION}"}}`,
200
+ SQS_TAGS: `[{"key":"testId","value":"${TEST_RUN_ID}"},{"key":"workerId","value":"${WORKER_ID}"}]`,
201
+ SQS_QUEUE_URL: SQS_QUEUE_URL,
202
+ SQS_REGION: SQS_REGION,
203
+ ARTILLERY_DISABLE_ENSURE: 'true',
204
+ WORKER_ID: WORKER_ID,
205
+ // Set test run ID for this Artillery process explicitly. This makes sure that $testId
206
+ // template variable is set to the same value for all Lambda workers as the one user
207
+ // sees on their terminal
208
+ ARTILLERY_TEST_RUN_ID: TEST_RUN_ID
209
+ // SHIP_LOGS: 'true',
210
+ },
211
+ ARTILLERY_CLOUD_API_KEY ? { ARTILLERY_CLOUD_API_KEY } : {},
212
+ ARTILLERY_CLOUD_ENDPOINT ? { ARTILLERY_CLOUD_ENDPOINT } : {},
213
+ ENV
214
+ );
215
+
216
+ const TEST_DATA_NODE_MODULES = `${TEST_DATA_LOCATION}/node_modules`;
217
+ const ARTILLERY_NODE_MODULES = '/artillery/node_modules';
218
+ const ARTILLERY_PATH =
219
+ ARTILLERY_BINARY_PATH || `${ARTILLERY_NODE_MODULES}/artillery/bin/run`;
220
+
221
+ // Set the plugin path to the legacy SQS plugin as well as to user's test data for third party plugins
222
+ env.ARTILLERY_PLUGIN_PATH = `${TEST_DATA_NODE_MODULES}:${ARTILLERY_NODE_MODULES}/artillery/lib/platform/aws-ecs/legacy/plugins`;
223
+ env.HOME = '/tmp';
224
+ env.NODE_PATH = ['/artillery/node_modules', TEST_DATA_NODE_MODULES].join(
225
+ path.delimiter
226
+ );
227
+
228
+ return runProcess(
229
+ NODE_BINARY_PATH || 'node',
230
+ [ARTILLERY_PATH].concat(ARTILLERY_ARGS),
231
+ { env, log: true }
232
+ );
233
+ }
234
+
235
+ module.exports = { handler, runProcess, execArtillery };
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "lambda-handler",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "artillery-plugin-sqs-reporter": "^1.2.0"
14
+ }
15
+ }
@@ -0,0 +1,29 @@
1
+ // Compute pricing for AWS Lambda
2
+ // GB/second divided by 10e10
3
+ // https://aws.amazon.com/lambda/pricing/
4
+ module.exports = {
5
+ base: {
6
+ x86_64: 1666670,
7
+ arm64: 1333340
8
+ },
9
+ 'af-south-1': {
10
+ x86_64: 2210000,
11
+ arm64: 1768000
12
+ },
13
+ 'ap-east-1': {
14
+ x86_64: 2292000,
15
+ arm64: 1830000
16
+ },
17
+ 'eu-south-1': {
18
+ x86_64: 1951720,
19
+ arm64: 1561380
20
+ },
21
+ 'me-south-1': {
22
+ x86_64: 2066670,
23
+ arm64: 1653340
24
+ },
25
+ 'me-central-1': {
26
+ x86_64: 2066670,
27
+ arm64: 1653340
28
+ }
29
+ };