@gatling.io/cli 3.11.4 → 3.11.5
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/package.json +9 -7
- package/target/dependencies/coursier.js +2 -1
- package/target/dependencies/versions.d.ts +1 -0
- package/target/dependencies/versions.js +3 -2
- package/target/enterprise.d.ts +30 -0
- package/target/{enterprisePackage.js → enterprise.js} +72 -4
- package/target/index.js +183 -15
- package/target/java.d.ts +5 -0
- package/target/java.js +38 -0
- package/target/readline.d.ts +2 -0
- package/target/readline.js +40 -0
- package/target/run.d.ts +5 -6
- package/target/run.js +7 -36
- package/target/enterprisePackage.d.ts +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gatling.io/cli",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.5",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"gatling": "target/index.js"
|
|
@@ -9,17 +9,19 @@
|
|
|
9
9
|
"types": "target/index.d.ts",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"archiver": "7.0.1",
|
|
12
|
-
"axios": "1.
|
|
13
|
-
"commander": "12.
|
|
12
|
+
"axios": "1.7.2",
|
|
13
|
+
"commander": "12.1.0",
|
|
14
14
|
"decompress": "4.2.1",
|
|
15
|
-
"esbuild": "0.
|
|
16
|
-
"esbuild-plugin-tsc": "0.4.0"
|
|
15
|
+
"esbuild": "0.23.0",
|
|
16
|
+
"esbuild-plugin-tsc": "0.4.0",
|
|
17
|
+
"readline-sync": "1.4.10"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@types/archiver": "6.0.2",
|
|
20
21
|
"@types/decompress": "4.2.7",
|
|
21
|
-
"@types/node": "20.
|
|
22
|
-
"
|
|
22
|
+
"@types/node": "20.14.9",
|
|
23
|
+
"@types/readline-sync": "1.4.8",
|
|
24
|
+
"prettier": "3.3.2",
|
|
23
25
|
"rimraf": "5.0.7",
|
|
24
26
|
"typescript": "5.4.5"
|
|
25
27
|
},
|
|
@@ -49,8 +49,9 @@ exports.installCoursier = installCoursier;
|
|
|
49
49
|
const resolveGatlingJsDependencies = async (coursierPath, javaHome) => {
|
|
50
50
|
const gatlingDep = `"io.gatling.highcharts:gatling-charts-highcharts:${versions_1.versions.gatling.core}"`;
|
|
51
51
|
const gatlingAdapterDep = `"io.gatling:gatling-jvm-to-js-adapter:${versions_1.versions.gatling.jsAdapter}"`;
|
|
52
|
+
const gatlingEnterprisePluginCommonsDep = `"io.gatling:gatling-enterprise-plugin-commons:${versions_1.versions.gatling.enterprisePluginCommons}"`;
|
|
52
53
|
const graalvmJsDep = `"org.graalvm.polyglot:js-community:${versions_1.versions.graalvm.js}"`;
|
|
53
|
-
return await resolveDependencies(coursierPath, javaHome, gatlingDep, gatlingAdapterDep, graalvmJsDep);
|
|
54
|
+
return await resolveDependencies(coursierPath, javaHome, gatlingDep, gatlingAdapterDep, gatlingEnterprisePluginCommonsDep, graalvmJsDep);
|
|
54
55
|
};
|
|
55
56
|
exports.resolveGatlingJsDependencies = resolveGatlingJsDependencies;
|
|
56
57
|
const resolveRecorderDependencies = async (coursierPath, javaHome) => {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { RunJavaProcessOptions } from "./java";
|
|
2
|
+
import { SimulationFile } from "./simulations";
|
|
3
|
+
export interface EnterprisePackageOptions {
|
|
4
|
+
bundleFile: string;
|
|
5
|
+
resourcesFolder: string;
|
|
6
|
+
packageFile: string;
|
|
7
|
+
simulations: SimulationFile[];
|
|
8
|
+
}
|
|
9
|
+
export declare const enterprisePackage: (options: EnterprisePackageOptions) => Promise<void>;
|
|
10
|
+
export interface EnterprisePluginOptions extends RunJavaProcessOptions {
|
|
11
|
+
bundleFile: string;
|
|
12
|
+
resourcesFolder: string;
|
|
13
|
+
resultsFolder: string;
|
|
14
|
+
url: string;
|
|
15
|
+
apiToken?: string;
|
|
16
|
+
controlPlaneUrl?: string;
|
|
17
|
+
nonInteractive: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface EnterpriseDeployOptions extends EnterprisePluginOptions {
|
|
20
|
+
packageDescriptorFilename: string;
|
|
21
|
+
packageFile: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const enterpriseDeploy: (options: EnterpriseDeployOptions) => Promise<void>;
|
|
24
|
+
export interface EnterpriseStartOptions extends EnterpriseDeployOptions {
|
|
25
|
+
enterpriseSimulation?: string;
|
|
26
|
+
runTitle?: string;
|
|
27
|
+
runDescription?: string;
|
|
28
|
+
waitForRunEnd?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare const enterpriseStart: (options: EnterpriseStartOptions) => Promise<void>;
|
|
@@ -3,19 +3,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.enterprisePackage = void 0;
|
|
6
|
+
exports.enterpriseStart = exports.enterpriseDeploy = exports.enterprisePackage = void 0;
|
|
7
7
|
const archiver_1 = __importDefault(require("archiver"));
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const promises_1 = require("stream/promises");
|
|
10
10
|
const zlib_1 = require("zlib");
|
|
11
11
|
const versions_1 = require("./dependencies/versions");
|
|
12
|
+
const java_1 = require("./java");
|
|
12
13
|
const log_1 = require("./log");
|
|
13
14
|
const enterprisePackage = async (options) => {
|
|
14
15
|
log_1.logger.info(`Packaging a Gatling simulation with options:
|
|
15
16
|
- bundleFile: ${options.bundleFile}
|
|
16
|
-
-
|
|
17
|
+
- packageFile: ${options.packageFile}`);
|
|
17
18
|
const manifest = generateManifest(options.simulations.map((s) => s.name));
|
|
18
|
-
const output = fs_1.default.createWriteStream(options.
|
|
19
|
+
const output = fs_1.default.createWriteStream(options.packageFile);
|
|
19
20
|
const archive = (0, archiver_1.default)("zip", {
|
|
20
21
|
zlib: { level: zlib_1.constants.Z_MAX_LEVEL }
|
|
21
22
|
});
|
|
@@ -29,7 +30,7 @@ const enterprisePackage = async (options) => {
|
|
|
29
30
|
archive.directory(options.resourcesFolder + "/", false);
|
|
30
31
|
archive.finalize();
|
|
31
32
|
await (0, promises_1.pipeline)(archive, output);
|
|
32
|
-
log_1.logger.info(`Package for Gatling Enterprise created at ${options.
|
|
33
|
+
log_1.logger.info(`Package for Gatling Enterprise created at ${options.packageFile}`);
|
|
33
34
|
};
|
|
34
35
|
exports.enterprisePackage = enterprisePackage;
|
|
35
36
|
const generateManifest = (simulationNames) => {
|
|
@@ -80,3 +81,70 @@ const generateManifest = (simulationNames) => {
|
|
|
80
81
|
}
|
|
81
82
|
return manifest;
|
|
82
83
|
};
|
|
84
|
+
const javaArgsFromPluginOptions = (options) => {
|
|
85
|
+
const javaArgs = [];
|
|
86
|
+
// Base
|
|
87
|
+
javaArgs.push(`-Dgatling.enterprise.url=${options.url}`);
|
|
88
|
+
if (options.apiToken !== undefined) {
|
|
89
|
+
javaArgs.push(`-Dgatling.enterprise.apiToken=${options.apiToken}`);
|
|
90
|
+
}
|
|
91
|
+
// Plugin configuration
|
|
92
|
+
if (options.controlPlaneUrl !== undefined) {
|
|
93
|
+
javaArgs.push(`-Dgatling.enterprise.controlPlaneUrl=${options.controlPlaneUrl}`);
|
|
94
|
+
}
|
|
95
|
+
javaArgs.push("-Dgatling.enterprise.buildTool=JS_CLI");
|
|
96
|
+
javaArgs.push(`-Dgatling.enterprise.pluginVersion=${versions_1.versions.gatling.jsAdapter}`);
|
|
97
|
+
if (options.nonInteractive) {
|
|
98
|
+
javaArgs.push(`-Dgatling.enterprise.batchMode=true`);
|
|
99
|
+
}
|
|
100
|
+
return javaArgs;
|
|
101
|
+
};
|
|
102
|
+
const javaArgsFromDeployOptions = (options) => {
|
|
103
|
+
const javaArgs = javaArgsFromPluginOptions(options);
|
|
104
|
+
// Descriptor file
|
|
105
|
+
javaArgs.push(`-Dgatling.enterprise.baseDirectory=${process.cwd()}`);
|
|
106
|
+
javaArgs.push(`-Dgatling.enterprise.packageDescriptorFilename=${options.packageDescriptorFilename}`);
|
|
107
|
+
// Deployment info
|
|
108
|
+
javaArgs.push(`-Dgatling.enterprise.packageFile=${options.packageFile}`);
|
|
109
|
+
if (process.env.npm_package_name !== undefined) {
|
|
110
|
+
javaArgs.push(`-Dgatling.enterprise.artifactId=${process.env.npm_package_name}`);
|
|
111
|
+
}
|
|
112
|
+
return javaArgs;
|
|
113
|
+
};
|
|
114
|
+
const enterpriseDeploy = async (options) => {
|
|
115
|
+
const additionalClasspathElements = [options.resourcesFolder];
|
|
116
|
+
const javaArgs = javaArgsFromDeployOptions(options);
|
|
117
|
+
if (process.env["DEBUG"] === "true") {
|
|
118
|
+
log_1.logger.debug("Java arguments:");
|
|
119
|
+
for (let i = 0; i < javaArgs.length; i++) {
|
|
120
|
+
log_1.logger.debug(" " + javaArgs[i]);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return (0, java_1.runJavaProcess)(options, "io.gatling.plugin.cli.EnterpriseDeploy", additionalClasspathElements, javaArgs, []);
|
|
124
|
+
};
|
|
125
|
+
exports.enterpriseDeploy = enterpriseDeploy;
|
|
126
|
+
const enterpriseStart = async (options) => {
|
|
127
|
+
const additionalClasspathElements = [options.resourcesFolder];
|
|
128
|
+
const javaArgs = javaArgsFromDeployOptions(options);
|
|
129
|
+
// Start
|
|
130
|
+
if (options.enterpriseSimulation !== undefined) {
|
|
131
|
+
javaArgs.push(`-Dgatling.enterprise.simulationName=${options.enterpriseSimulation}`);
|
|
132
|
+
}
|
|
133
|
+
if (options.runTitle !== undefined) {
|
|
134
|
+
javaArgs.push(`-Dgatling.enterprise.runTitle=${options.runTitle}`);
|
|
135
|
+
}
|
|
136
|
+
if (options.runDescription !== undefined) {
|
|
137
|
+
javaArgs.push(`-Dgatling.enterprise.runDescription=${options.runDescription}`);
|
|
138
|
+
}
|
|
139
|
+
if (options.waitForRunEnd) {
|
|
140
|
+
javaArgs.push("-Dgatling.enterprise.waitForRunEnd=true");
|
|
141
|
+
}
|
|
142
|
+
if (process.env["DEBUG"] === "true") {
|
|
143
|
+
log_1.logger.debug("Java arguments:");
|
|
144
|
+
for (let i = 0; i < javaArgs.length; i++) {
|
|
145
|
+
log_1.logger.debug(" " + javaArgs[i]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return (0, java_1.runJavaProcess)(options, "io.gatling.plugin.cli.EnterpriseStart", additionalClasspathElements, javaArgs, []);
|
|
149
|
+
};
|
|
150
|
+
exports.enterpriseStart = enterpriseStart;
|
package/target/index.js
CHANGED
|
@@ -8,9 +8,10 @@ const commander_1 = require("commander");
|
|
|
8
8
|
const os_1 = __importDefault(require("os"));
|
|
9
9
|
const bundle_1 = require("./bundle");
|
|
10
10
|
const dependencies_1 = require("./dependencies");
|
|
11
|
-
const
|
|
11
|
+
const enterprise_1 = require("./enterprise");
|
|
12
12
|
const simulations_1 = require("./simulations");
|
|
13
13
|
const log_1 = require("./log");
|
|
14
|
+
const readline_1 = require("./readline");
|
|
14
15
|
const run_1 = require("./run");
|
|
15
16
|
const program = new commander_1.Command()
|
|
16
17
|
.name("gatling-js-cli")
|
|
@@ -20,7 +21,7 @@ const gatlingHomeOption = new commander_1.Option("--gatling-home <value>", 'The
|
|
|
20
21
|
const gatlingHomeDirWithDefaults = (options) => options.gatlingHome || `${os_1.default.homedir()}/.gatling`;
|
|
21
22
|
const sourcesFolderOption = new commander_1.Option("--sources-folder <value>", "The sources folder path").default("src");
|
|
22
23
|
const simulationOption = new commander_1.Option("--simulation <value>", "The simulation entry point function name (default: if only one *.gatling.js or *.gatling.ts file is found, will execute that simulation)");
|
|
23
|
-
const simulationWithDefaults = (options, simulationsFound) => {
|
|
24
|
+
const simulationWithDefaults = (options, simulationsFound, interactive) => {
|
|
24
25
|
if (options.simulation !== undefined) {
|
|
25
26
|
return options.simulation;
|
|
26
27
|
}
|
|
@@ -30,6 +31,17 @@ const simulationWithDefaults = (options, simulationsFound) => {
|
|
|
30
31
|
else if (simulationsFound.length === 0) {
|
|
31
32
|
throw new Error("No simulation found, simulations must be defined in a <simulation name>.gatling.js or <simulation name>.gatling.ts file)");
|
|
32
33
|
}
|
|
34
|
+
else if (interactive) {
|
|
35
|
+
const idx = (0, readline_1.keyInSelectPaginated)(simulationsFound.map((s) => s.name).sort((a, b) => a.localeCompare(b)), "Choose a simulation to run");
|
|
36
|
+
if (idx >= 0) {
|
|
37
|
+
const simulation = simulationsFound[idx].name;
|
|
38
|
+
log_1.logger.info(`Simulation '${simulation}' was chosen.`);
|
|
39
|
+
return simulation;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
throw new Error("Simulation choice was cancelled.");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
33
45
|
else {
|
|
34
46
|
throw new Error(`Several simulations found, specify one using the --simulation option (available simulations: ${simulationsFound.map((s) => s.name)})`);
|
|
35
47
|
}
|
|
@@ -42,12 +54,12 @@ const validateBundleFile = (options) => {
|
|
|
42
54
|
}
|
|
43
55
|
return options.bundleFile;
|
|
44
56
|
};
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
if (!options.
|
|
48
|
-
throw Error(`'${options.
|
|
57
|
+
const packageFileOption = new commander_1.Option("--package-file <value>", "The target package file path when packaging simulations for Gatling Enterprise (must have a .zip extension)").default("target/package.zip");
|
|
58
|
+
const validatePackageFile = (options) => {
|
|
59
|
+
if (!options.packageFile.endsWith(".zip")) {
|
|
60
|
+
throw Error(`'${options.packageFile}' is not a valid package file path: should have a .zip extension`);
|
|
49
61
|
}
|
|
50
|
-
return options.
|
|
62
|
+
return options.packageFile;
|
|
51
63
|
};
|
|
52
64
|
const resourcesFolderOption = new commander_1.Option("--resources-folder <value>", "The resources folder path").default("resources");
|
|
53
65
|
const resultsFolderOption = new commander_1.Option("--results-folder <value>", "The results folder path").default("target/gatling");
|
|
@@ -57,6 +69,29 @@ const typescriptWithDefaults = (options, simulationsFound) => options.typescript
|
|
|
57
69
|
: simulationsFound.findIndex((s) => s.type === "typescript") >= 0;
|
|
58
70
|
const graalvmHomeMandatoryOption = new commander_1.Option("--graalvm-home <value>", "Path to the GraalVM home").makeOptionMandatory(true);
|
|
59
71
|
const jvmClasspathMandatoryOption = new commander_1.Option("--jvm-classpath <value>", "The classpath containing all Gatling JVM components").makeOptionMandatory(true);
|
|
72
|
+
const memoryOption = new commander_1.Option("--memory <value>", "Heap space memory size in MiB for Gatling. Half the total available memory is usually a good default, as the Gatling process will use more memory than just the heap space.").argParser((value) => {
|
|
73
|
+
const parsedValue = parseInt(value, 10);
|
|
74
|
+
if (isNaN(parsedValue)) {
|
|
75
|
+
throw new Error(`${value} is not a valid memory size, must be an integer number`);
|
|
76
|
+
}
|
|
77
|
+
return parsedValue;
|
|
78
|
+
});
|
|
79
|
+
const nonInteractiveOption = new commander_1.Option("--non-interactive", "Switch to non-interactive mode and fail if no simulation is explicitly specified").default(false);
|
|
80
|
+
const runOptionsArgument = new commander_1.Argument("[optionKey=optionValue...]", "Specify one or more option which can be read in the simulation script with the getOption() function; format must be key=value");
|
|
81
|
+
const parseRunOptions = (args) => {
|
|
82
|
+
const parsedOptions = {};
|
|
83
|
+
for (const arg of args) {
|
|
84
|
+
const i = arg.indexOf("=");
|
|
85
|
+
if (i < 0) {
|
|
86
|
+
throw Error(`Option '${arg}' is not valid: format should be key=value`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const key = arg.slice(0, i).trim();
|
|
90
|
+
parsedOptions[key] = arg.slice(i + 1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return parsedOptions;
|
|
94
|
+
};
|
|
60
95
|
program
|
|
61
96
|
.command("install")
|
|
62
97
|
.description("Install all required components and dependencies for Gatling")
|
|
@@ -90,20 +125,26 @@ program
|
|
|
90
125
|
.addOption(bundleFileOption)
|
|
91
126
|
.addOption(resourcesFolderOption)
|
|
92
127
|
.addOption(resultsFolderOption)
|
|
93
|
-
.
|
|
128
|
+
.addOption(memoryOption)
|
|
129
|
+
.addArgument(runOptionsArgument)
|
|
130
|
+
.action(async (args, options) => {
|
|
94
131
|
const graalvmHome = options.graalvmHome;
|
|
95
132
|
const jvmClasspath = options.jvmClasspath;
|
|
96
133
|
const simulation = options.simulation;
|
|
97
134
|
const bundleFile = validateBundleFile(options);
|
|
98
135
|
const resourcesFolder = options.resourcesFolder;
|
|
99
136
|
const resultsFolder = options.resultsFolder;
|
|
137
|
+
const memory = options.memory;
|
|
138
|
+
const runOptions = parseRunOptions(args);
|
|
100
139
|
await (0, run_1.runSimulation)({
|
|
101
140
|
graalvmHome,
|
|
102
141
|
jvmClasspath,
|
|
103
142
|
simulation: simulation,
|
|
104
143
|
bundleFile,
|
|
105
144
|
resourcesFolder,
|
|
106
|
-
resultsFolder
|
|
145
|
+
resultsFolder,
|
|
146
|
+
memory,
|
|
147
|
+
runOptions
|
|
107
148
|
});
|
|
108
149
|
});
|
|
109
150
|
program
|
|
@@ -116,21 +157,36 @@ program
|
|
|
116
157
|
.addOption(resourcesFolderOption)
|
|
117
158
|
.addOption(resultsFolderOption)
|
|
118
159
|
.addOption(gatlingHomeOption)
|
|
119
|
-
.
|
|
160
|
+
.addOption(memoryOption)
|
|
161
|
+
.addOption(nonInteractiveOption)
|
|
162
|
+
.addArgument(runOptionsArgument)
|
|
163
|
+
.action(async (args, options) => {
|
|
120
164
|
const gatlingHome = gatlingHomeDirWithDefaults(options);
|
|
121
165
|
const sourcesFolder = options.sourcesFolder;
|
|
122
166
|
const bundleFile = validateBundleFile(options);
|
|
123
167
|
const resourcesFolder = options.resourcesFolder;
|
|
124
168
|
const resultsFolder = options.resultsFolder;
|
|
169
|
+
const memory = options.memory;
|
|
170
|
+
const nonInteractive = options.nonInteractive;
|
|
171
|
+
const runOptions = parseRunOptions(args);
|
|
125
172
|
const simulations = await (0, simulations_1.findSimulations)(sourcesFolder);
|
|
126
173
|
const typescript = typescriptWithDefaults(options, simulations);
|
|
127
|
-
const simulation = simulationWithDefaults(options, simulations);
|
|
174
|
+
const simulation = simulationWithDefaults(options, simulations, !nonInteractive);
|
|
128
175
|
const { graalvmHome, coursierBinary, jvmClasspath } = await (0, dependencies_1.installGatlingJs)({ gatlingHome });
|
|
129
176
|
log_1.logger.debug(`graalvmHome=${graalvmHome}`);
|
|
130
177
|
log_1.logger.debug(`coursierBinary=${coursierBinary}`);
|
|
131
178
|
log_1.logger.debug(`jvmClasspath=${jvmClasspath}`);
|
|
132
179
|
await (0, bundle_1.bundle)({ sourcesFolder, bundleFile, typescript, simulations });
|
|
133
|
-
await (0, run_1.runSimulation)({
|
|
180
|
+
await (0, run_1.runSimulation)({
|
|
181
|
+
graalvmHome,
|
|
182
|
+
jvmClasspath,
|
|
183
|
+
simulation,
|
|
184
|
+
bundleFile,
|
|
185
|
+
resourcesFolder,
|
|
186
|
+
resultsFolder,
|
|
187
|
+
memory,
|
|
188
|
+
runOptions
|
|
189
|
+
});
|
|
134
190
|
});
|
|
135
191
|
program
|
|
136
192
|
.command("recorder")
|
|
@@ -157,16 +213,128 @@ program
|
|
|
157
213
|
.addOption(sourcesFolderOption)
|
|
158
214
|
.addOption(resourcesFolderOption)
|
|
159
215
|
.addOption(bundleFileOption)
|
|
160
|
-
.addOption(
|
|
216
|
+
.addOption(packageFileOption)
|
|
161
217
|
.addOption(typescriptOption)
|
|
162
218
|
.action(async (options) => {
|
|
163
219
|
const sourcesFolder = options.sourcesFolder;
|
|
164
220
|
const resourcesFolder = options.resourcesFolder;
|
|
165
221
|
const bundleFile = validateBundleFile(options);
|
|
166
|
-
const
|
|
222
|
+
const packageFile = validatePackageFile(options);
|
|
167
223
|
const simulations = await (0, simulations_1.findSimulations)(sourcesFolder);
|
|
168
224
|
const typescript = typescriptWithDefaults(options, simulations);
|
|
169
225
|
await (0, bundle_1.bundle)({ sourcesFolder, bundleFile, typescript, simulations });
|
|
170
|
-
await (0,
|
|
226
|
+
await (0, enterprise_1.enterprisePackage)({ bundleFile, resourcesFolder, packageFile, simulations });
|
|
227
|
+
});
|
|
228
|
+
const urlOption = new commander_1.Option("--url <value>", "URL of Gatling Enterprise")
|
|
229
|
+
.default("https://cloud.gatling.io")
|
|
230
|
+
.hideHelp();
|
|
231
|
+
const apiTokenOption = new commander_1.Option("--api-token <value>", "API Token on Gatling Enterprise. Prefer configuration using `GATLING_ENTERPRISE_API_TOKEN` environment variable.");
|
|
232
|
+
// Plugin configuration
|
|
233
|
+
const controlPlaneUrlOption = new commander_1.Option("--control-plane-url <value>", "URL of a control plane for Gatling Enterprise providing a private repository. If this parameter is provided, packages will be registered as private packages and uploaded through this private control plane.");
|
|
234
|
+
// Descriptor file
|
|
235
|
+
const packageDescriptorFilenameOption = new commander_1.Option("--package-descriptor-filename <value>", "Path to a package descriptor inside the .gatling folder").default("package.conf");
|
|
236
|
+
const enterpriseBundleAndPackage = async (options) => {
|
|
237
|
+
const gatlingHome = gatlingHomeDirWithDefaults(options);
|
|
238
|
+
const sourcesFolder = options.sourcesFolder;
|
|
239
|
+
const bundleFile = validateBundleFile(options);
|
|
240
|
+
const resourcesFolder = options.resourcesFolder;
|
|
241
|
+
const resultsFolder = options.resultsFolder;
|
|
242
|
+
const simulations = await (0, simulations_1.findSimulations)(sourcesFolder);
|
|
243
|
+
const typescript = typescriptWithDefaults(options, simulations);
|
|
244
|
+
// Base
|
|
245
|
+
const url = options.url;
|
|
246
|
+
const apiToken = options.apiToken;
|
|
247
|
+
// Plugin configuration
|
|
248
|
+
const controlPlaneUrl = options.controlPlaneUrl;
|
|
249
|
+
const nonInteractive = options.nonInteractive;
|
|
250
|
+
// Descriptor file
|
|
251
|
+
const packageDescriptorFilename = options.packageDescriptorFilename;
|
|
252
|
+
// Deployment info
|
|
253
|
+
const packageFile = validatePackageFile(options);
|
|
254
|
+
const { graalvmHome, coursierBinary, jvmClasspath } = await (0, dependencies_1.installGatlingJs)({ gatlingHome });
|
|
255
|
+
log_1.logger.debug(`graalvmHome=${graalvmHome}`);
|
|
256
|
+
log_1.logger.debug(`coursierBinary=${coursierBinary}`);
|
|
257
|
+
log_1.logger.debug(`jvmClasspath=${jvmClasspath}`);
|
|
258
|
+
await (0, bundle_1.bundle)({ sourcesFolder, bundleFile, typescript, simulations });
|
|
259
|
+
await (0, enterprise_1.enterprisePackage)({ bundleFile, resourcesFolder, packageFile, simulations });
|
|
260
|
+
return {
|
|
261
|
+
graalvmHome,
|
|
262
|
+
jvmClasspath,
|
|
263
|
+
bundleFile,
|
|
264
|
+
resourcesFolder,
|
|
265
|
+
resultsFolder,
|
|
266
|
+
// Base
|
|
267
|
+
url,
|
|
268
|
+
apiToken,
|
|
269
|
+
// Plugin configuration
|
|
270
|
+
controlPlaneUrl,
|
|
271
|
+
nonInteractive,
|
|
272
|
+
// Descriptor file
|
|
273
|
+
packageDescriptorFilename,
|
|
274
|
+
// Deployment info
|
|
275
|
+
packageFile
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
program
|
|
279
|
+
.command("enterprise-deploy")
|
|
280
|
+
.description("Deploy a package and configured simulations")
|
|
281
|
+
.addOption(sourcesFolderOption)
|
|
282
|
+
.addOption(resourcesFolderOption)
|
|
283
|
+
.addOption(bundleFileOption)
|
|
284
|
+
.addOption(resultsFolderOption)
|
|
285
|
+
// Base
|
|
286
|
+
.addOption(urlOption)
|
|
287
|
+
.addOption(apiTokenOption)
|
|
288
|
+
// Plugin configuration
|
|
289
|
+
.addOption(controlPlaneUrlOption)
|
|
290
|
+
.addOption(nonInteractiveOption)
|
|
291
|
+
// Descriptor file
|
|
292
|
+
.addOption(packageDescriptorFilenameOption)
|
|
293
|
+
// Deployment info
|
|
294
|
+
.addOption(packageFileOption)
|
|
295
|
+
.action(async (options) => {
|
|
296
|
+
const deployOptions = await enterpriseBundleAndPackage(options);
|
|
297
|
+
await (0, enterprise_1.enterpriseDeploy)(deployOptions);
|
|
298
|
+
});
|
|
299
|
+
// Deployment info
|
|
300
|
+
const enterpriseSimulationOption = new commander_1.Option("--enterprise-simulation <value>", "Specify the simulation name directly to bypass the prompt using the following command.");
|
|
301
|
+
const runTitleOption = new commander_1.Option("--run-title <value>", "Allows setting a title for your run reports.");
|
|
302
|
+
const runDescriptionOption = new commander_1.Option("--run-description <value>", "Allows setting a description for your run reports summary.");
|
|
303
|
+
const waitForRunEndOption = new commander_1.Option("--wait-for-run-end", "Wait for the result after starting the simulation on Gatling Enterprise, and complete with an error if the simulation ends with any error status").default(false);
|
|
304
|
+
program
|
|
305
|
+
.command("enterprise-start")
|
|
306
|
+
.description("Start a simulation deployed with `enterprise-deploy`")
|
|
307
|
+
.addOption(sourcesFolderOption)
|
|
308
|
+
.addOption(resourcesFolderOption)
|
|
309
|
+
.addOption(bundleFileOption)
|
|
310
|
+
.addOption(resultsFolderOption)
|
|
311
|
+
// Base
|
|
312
|
+
.addOption(urlOption)
|
|
313
|
+
.addOption(apiTokenOption)
|
|
314
|
+
// Plugin configuration
|
|
315
|
+
.addOption(controlPlaneUrlOption)
|
|
316
|
+
.addOption(nonInteractiveOption)
|
|
317
|
+
// Descriptor file
|
|
318
|
+
.addOption(packageDescriptorFilenameOption)
|
|
319
|
+
// Deployment info
|
|
320
|
+
.addOption(packageFileOption)
|
|
321
|
+
// Start
|
|
322
|
+
.addOption(enterpriseSimulationOption)
|
|
323
|
+
.addOption(runTitleOption)
|
|
324
|
+
.addOption(runDescriptionOption)
|
|
325
|
+
.addOption(waitForRunEndOption)
|
|
326
|
+
.action(async (options) => {
|
|
327
|
+
const deployOptions = await enterpriseBundleAndPackage(options);
|
|
328
|
+
if (options.nonInteractive && options.enterpriseSimulation === undefined) {
|
|
329
|
+
throw new Error(`No simulation specified when using non-interactive mode`);
|
|
330
|
+
}
|
|
331
|
+
await (0, enterprise_1.enterpriseStart)({
|
|
332
|
+
...deployOptions,
|
|
333
|
+
// Start
|
|
334
|
+
enterpriseSimulation: options.enterpriseSimulation,
|
|
335
|
+
runTitle: options.runTitle,
|
|
336
|
+
runDescription: options.runDescription,
|
|
337
|
+
waitForRunEnd: options.waitForRunEnd
|
|
338
|
+
});
|
|
171
339
|
});
|
|
172
340
|
program.parse(process.argv);
|
package/target/java.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export interface RunJavaProcessOptions {
|
|
2
|
+
graalvmHome: string;
|
|
3
|
+
jvmClasspath: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const runJavaProcess: (options: RunJavaProcessOptions, mainClass: string, additionalClasspathElements: string[], javaArgs: string[], mainClassArgs: string[]) => Promise<void>;
|
package/target/java.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runJavaProcess = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const os_1 = require("./dependencies/os");
|
|
6
|
+
const log_1 = require("./log");
|
|
7
|
+
const runJavaProcess = (options, mainClass, additionalClasspathElements, javaArgs, mainClassArgs) => {
|
|
8
|
+
const command = `${options.graalvmHome}/bin/java`;
|
|
9
|
+
const classpathSeparator = os_1.osType === "Windows_NT" ? ";" : ":";
|
|
10
|
+
const classpath = [...additionalClasspathElements, options.jvmClasspath].join(classpathSeparator);
|
|
11
|
+
const allArgs = [
|
|
12
|
+
"-server",
|
|
13
|
+
"-XX:+HeapDumpOnOutOfMemoryError",
|
|
14
|
+
"-XX:MaxInlineLevel=20",
|
|
15
|
+
"-XX:MaxTrivialSize=12",
|
|
16
|
+
"-classpath",
|
|
17
|
+
classpath,
|
|
18
|
+
...javaArgs,
|
|
19
|
+
mainClass,
|
|
20
|
+
...mainClassArgs
|
|
21
|
+
];
|
|
22
|
+
const spawned = (0, child_process_1.spawn)(command, allArgs, {
|
|
23
|
+
env: process.env,
|
|
24
|
+
stdio: [process.stdin, process.stdout, process.stderr]
|
|
25
|
+
});
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
spawned.on("error", (error) => log_1.logger.error("Failed to run Gatling process: " + error.toString()));
|
|
28
|
+
spawned.on("close", (code) => {
|
|
29
|
+
if (code === 0) {
|
|
30
|
+
resolve();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
reject(Error("Gatling process finished with code " + code));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
exports.runJavaProcess = runJavaProcess;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.keyInSelectPaginated = void 0;
|
|
4
|
+
const readline_sync_1 = require("readline-sync");
|
|
5
|
+
// Inspired by https://github.com/anseki/readline-sync/issues/60#issuecomment-324533678
|
|
6
|
+
// Pagination avoids very long lists to scroll though, as well as the hard limit at 35 items for keyInSelect
|
|
7
|
+
const keyInSelectPaginated = (items, query, options) => {
|
|
8
|
+
if (items.length === 0) {
|
|
9
|
+
return -1;
|
|
10
|
+
}
|
|
11
|
+
const maxItemsPerPage = 10;
|
|
12
|
+
const maxPageIndex = Math.ceil(items.length / maxItemsPerPage) - 1;
|
|
13
|
+
let pageIndex = 0;
|
|
14
|
+
while (true) {
|
|
15
|
+
const pageItems = [];
|
|
16
|
+
let indexPrev = -1;
|
|
17
|
+
let indexNext = -1;
|
|
18
|
+
if (pageIndex > 0) {
|
|
19
|
+
pageItems.push(`(PREVIOUS ${maxItemsPerPage} items)`);
|
|
20
|
+
indexPrev = pageItems.length - 1;
|
|
21
|
+
}
|
|
22
|
+
pageItems.push(...items.slice(pageIndex * maxItemsPerPage, (pageIndex + 1) * maxItemsPerPage));
|
|
23
|
+
if (pageIndex < maxPageIndex) {
|
|
24
|
+
pageItems.push(`(NEXT ${pageIndex < maxPageIndex - 1 ? maxItemsPerPage : items.length - maxItemsPerPage * (pageIndex + 1)} item(s))`);
|
|
25
|
+
indexNext = pageItems.length - 1;
|
|
26
|
+
}
|
|
27
|
+
console.log("\x1B[2J"); // clear screen
|
|
28
|
+
const index = (0, readline_sync_1.keyInSelect)(pageItems, query, options);
|
|
29
|
+
if (indexPrev !== -1 && index === indexPrev) {
|
|
30
|
+
pageIndex--;
|
|
31
|
+
}
|
|
32
|
+
else if (indexNext !== -1 && index === indexNext) {
|
|
33
|
+
pageIndex++;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return index === -1 ? index : index + pageIndex * maxItemsPerPage - (indexPrev === -1 ? 0 : 1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.keyInSelectPaginated = keyInSelectPaginated;
|
package/target/run.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
jvmClasspath: string;
|
|
4
|
-
}
|
|
5
|
-
export interface RunSimulationOptions extends RunOptions {
|
|
1
|
+
import { RunJavaProcessOptions } from "./java";
|
|
2
|
+
export interface RunSimulationOptions extends RunJavaProcessOptions {
|
|
6
3
|
simulation: string;
|
|
7
4
|
bundleFile: string;
|
|
8
5
|
resourcesFolder: string;
|
|
9
6
|
resultsFolder: string;
|
|
7
|
+
memory?: number;
|
|
8
|
+
runOptions: Record<string, string>;
|
|
10
9
|
}
|
|
11
|
-
export interface RunRecorderOptions extends
|
|
10
|
+
export interface RunRecorderOptions extends RunJavaProcessOptions {
|
|
12
11
|
sourcesFolder: string;
|
|
13
12
|
typescript: boolean;
|
|
14
13
|
resourcesFolder: string;
|
package/target/run.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runRecorder = exports.runSimulation = void 0;
|
|
4
|
-
const child_process_1 = require("child_process");
|
|
5
4
|
const log_1 = require("./log");
|
|
6
5
|
const versions_1 = require("./dependencies/versions");
|
|
7
|
-
const
|
|
6
|
+
const java_1 = require("./java");
|
|
8
7
|
const runSimulation = async (options) => {
|
|
9
8
|
log_1.logger.info(`Running a Gatling simulation with options:
|
|
10
9
|
- simulation: ${options.simulation}
|
|
@@ -12,9 +11,12 @@ const runSimulation = async (options) => {
|
|
|
12
11
|
- resourcesFolder: ${options.resourcesFolder}
|
|
13
12
|
- resultsFolder: ${options.resultsFolder}`);
|
|
14
13
|
const additionalClasspathElements = [options.resourcesFolder];
|
|
14
|
+
const memoryArgs = options.memory !== undefined ? [`-Xms${options.memory}M`, `-Xmx${options.memory}M`] : [];
|
|
15
15
|
const javaArgs = [
|
|
16
|
+
...Object.entries(options.runOptions).map(([key, value]) => `-D${key}=${value}`),
|
|
16
17
|
`-Dgatling.js.bundle.filePath=${options.bundleFile}`,
|
|
17
|
-
`-Dgatling.js.simulation=${options.simulation}
|
|
18
|
+
`-Dgatling.js.simulation=${options.simulation}`,
|
|
19
|
+
...memoryArgs
|
|
18
20
|
];
|
|
19
21
|
const simulationArgs = [
|
|
20
22
|
"--results-folder",
|
|
@@ -26,7 +28,7 @@ const runSimulation = async (options) => {
|
|
|
26
28
|
"--build-tool-version",
|
|
27
29
|
versions_1.versions.gatling.jsAdapter
|
|
28
30
|
];
|
|
29
|
-
return
|
|
31
|
+
return (0, java_1.runJavaProcess)(options, "io.gatling.app.Gatling", additionalClasspathElements, javaArgs, simulationArgs);
|
|
30
32
|
};
|
|
31
33
|
exports.runSimulation = runSimulation;
|
|
32
34
|
const runRecorder = async (options) => {
|
|
@@ -42,37 +44,6 @@ const runRecorder = async (options) => {
|
|
|
42
44
|
"--format",
|
|
43
45
|
options.typescript ? "typescript" : "javascript"
|
|
44
46
|
];
|
|
45
|
-
return
|
|
47
|
+
return (0, java_1.runJavaProcess)(options, "io.gatling.recorder.GatlingRecorder", [], [], recorderArgs);
|
|
46
48
|
};
|
|
47
49
|
exports.runRecorder = runRecorder;
|
|
48
|
-
const run = (options, mainClass, additionalClasspathElements, javaArgs, mainClassArgs) => {
|
|
49
|
-
const command = `${options.graalvmHome}/bin/java`;
|
|
50
|
-
const classpathSeparator = os_1.osType === "Windows_NT" ? ";" : ":";
|
|
51
|
-
const classpath = [...additionalClasspathElements, options.jvmClasspath].join(classpathSeparator);
|
|
52
|
-
const allArgs = [
|
|
53
|
-
"-server",
|
|
54
|
-
"-XX:+HeapDumpOnOutOfMemoryError",
|
|
55
|
-
"-XX:MaxInlineLevel=20",
|
|
56
|
-
"-XX:MaxTrivialSize=12",
|
|
57
|
-
"-Xmx1G",
|
|
58
|
-
"-classpath",
|
|
59
|
-
classpath,
|
|
60
|
-
...javaArgs,
|
|
61
|
-
mainClass,
|
|
62
|
-
...mainClassArgs
|
|
63
|
-
];
|
|
64
|
-
const process = (0, child_process_1.spawn)(command, allArgs);
|
|
65
|
-
return new Promise((resolve, reject) => {
|
|
66
|
-
process.stdout.on("data", (data) => log_1.logger.info(data.toString()));
|
|
67
|
-
process.stderr.on("data", (data) => log_1.logger.error(data.toString()));
|
|
68
|
-
process.on("error", (error) => log_1.logger.error("Failed to run Gatling process: " + error.toString()));
|
|
69
|
-
process.on("close", (code) => {
|
|
70
|
-
if (code === 0) {
|
|
71
|
-
resolve();
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
reject(Error("Gatling process finished with code " + code));
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { SimulationFile } from "./simulations";
|
|
2
|
-
export interface EnterprisePackageOptions {
|
|
3
|
-
bundleFile: string;
|
|
4
|
-
resourcesFolder: string;
|
|
5
|
-
enterprisePackageFile: string;
|
|
6
|
-
simulations: SimulationFile[];
|
|
7
|
-
}
|
|
8
|
-
export declare const enterprisePackage: (options: EnterprisePackageOptions) => Promise<void>;
|