genlayer 0.11.0 → 0.12.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.
- package/CHANGELOG.md +9 -0
- package/dist/index.js +75 -40
- package/package.json +1 -1
- package/src/commands/general/index.ts +9 -0
- package/src/commands/general/init.ts +1 -1
- package/src/commands/general/stop.ts +25 -0
- package/src/lib/interfaces/ISimulatorService.ts +3 -2
- package/src/lib/services/simulator.ts +40 -26
- package/tests/actions/stop.test.ts +58 -0
- package/tests/commands/stop.test.ts +27 -0
- package/tests/services/simulator.test.ts +32 -2
- package/vitest.config.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## 0.12.0 (2025-02-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* Add `stop` Command and Improve Docker Container Management ([#178](https://github.com/yeagerai/genlayer-cli/issues/178)) ([dbae62c](https://github.com/yeagerai/genlayer-cli/commit/dbae62cd6ea0c90ee7fb6953112006f9dff729c3))
|
|
9
|
+
|
|
10
|
+
## 0.11.1 (2025-02-05)
|
|
11
|
+
|
|
3
12
|
## 0.11.0 (2025-01-31)
|
|
4
13
|
|
|
5
14
|
|
package/dist/index.js
CHANGED
|
@@ -54537,7 +54537,7 @@ var {
|
|
|
54537
54537
|
} = import_index.default;
|
|
54538
54538
|
|
|
54539
54539
|
// package.json
|
|
54540
|
-
var version = "0.
|
|
54540
|
+
var version = "0.12.0";
|
|
54541
54541
|
var package_default = {
|
|
54542
54542
|
name: "genlayer",
|
|
54543
54543
|
version,
|
|
@@ -55272,6 +55272,32 @@ var SimulatorService = class {
|
|
|
55272
55272
|
this.composeOptions = "";
|
|
55273
55273
|
this.docker = new import_dockerode.default();
|
|
55274
55274
|
}
|
|
55275
|
+
readEnvConfigValue(key) {
|
|
55276
|
+
const envFilePath = path2.join(this.location, ".env");
|
|
55277
|
+
const envConfig = dotenv.parse(fs5.readFileSync(envFilePath, "utf8"));
|
|
55278
|
+
return envConfig[key];
|
|
55279
|
+
}
|
|
55280
|
+
async getGenlayerContainers() {
|
|
55281
|
+
const containers = await this.docker.listContainers({ all: true });
|
|
55282
|
+
return containers.filter(
|
|
55283
|
+
(container) => container.Names.some(
|
|
55284
|
+
(name) => name.startsWith(CONTAINERS_NAME_PREFIX) || name.includes("ollama")
|
|
55285
|
+
)
|
|
55286
|
+
);
|
|
55287
|
+
}
|
|
55288
|
+
async stopAndRemoveContainers(remove = false) {
|
|
55289
|
+
const genlayerContainers = await this.getGenlayerContainers();
|
|
55290
|
+
for (const containerInfo of genlayerContainers) {
|
|
55291
|
+
const container = this.docker.getContainer(containerInfo.Id);
|
|
55292
|
+
if (containerInfo.State === "running") {
|
|
55293
|
+
await container.stop();
|
|
55294
|
+
}
|
|
55295
|
+
const isOllamaContainer = containerInfo.Names.some((name) => name.includes("ollama"));
|
|
55296
|
+
if (remove && !isOllamaContainer) {
|
|
55297
|
+
await container.remove();
|
|
55298
|
+
}
|
|
55299
|
+
}
|
|
55300
|
+
}
|
|
55275
55301
|
addConfigToEnvFile(newConfig) {
|
|
55276
55302
|
const envFilePath = path2.join(this.location, ".env");
|
|
55277
55303
|
const envConfig = dotenv.parse(fs5.readFileSync(envFilePath, "utf8"));
|
|
@@ -55289,11 +55315,6 @@ var SimulatorService = class {
|
|
|
55289
55315
|
getComposeOptions() {
|
|
55290
55316
|
return this.composeOptions;
|
|
55291
55317
|
}
|
|
55292
|
-
readEnvConfigValue(key) {
|
|
55293
|
-
const envFilePath = path2.join(this.location, ".env");
|
|
55294
|
-
const envConfig = dotenv.parse(fs5.readFileSync(envFilePath, "utf8"));
|
|
55295
|
-
return envConfig[key];
|
|
55296
|
-
}
|
|
55297
55318
|
async checkCliVersion() {
|
|
55298
55319
|
const update = await (0, import_update_check.default)(package_default);
|
|
55299
55320
|
if (update && update.latest !== package_default.version) {
|
|
@@ -55402,21 +55423,11 @@ Run npm install -g genlayer to update
|
|
|
55402
55423
|
await openUrl(this.getFrontendUrl());
|
|
55403
55424
|
return true;
|
|
55404
55425
|
}
|
|
55426
|
+
async stopDockerContainers() {
|
|
55427
|
+
await this.stopAndRemoveContainers(false);
|
|
55428
|
+
}
|
|
55405
55429
|
async resetDockerContainers() {
|
|
55406
|
-
|
|
55407
|
-
const genlayerContainers = containers.filter(
|
|
55408
|
-
(container) => container.Names.some(
|
|
55409
|
-
(name) => name.startsWith(CONTAINERS_NAME_PREFIX)
|
|
55410
|
-
)
|
|
55411
|
-
);
|
|
55412
|
-
for (const containerInfo of genlayerContainers) {
|
|
55413
|
-
const container = this.docker.getContainer(containerInfo.Id);
|
|
55414
|
-
if (containerInfo.State === "running") {
|
|
55415
|
-
await container.stop();
|
|
55416
|
-
}
|
|
55417
|
-
await container.remove();
|
|
55418
|
-
}
|
|
55419
|
-
return true;
|
|
55430
|
+
await this.stopAndRemoveContainers(true);
|
|
55420
55431
|
}
|
|
55421
55432
|
async resetDockerImages() {
|
|
55422
55433
|
const images = await this.docker.listImages();
|
|
@@ -55427,7 +55438,6 @@ Run npm install -g genlayer to update
|
|
|
55427
55438
|
const image = this.docker.getImage(imageInfo.Id);
|
|
55428
55439
|
await image.remove({ force: true });
|
|
55429
55440
|
}
|
|
55430
|
-
return true;
|
|
55431
55441
|
}
|
|
55432
55442
|
async cleanDatabase() {
|
|
55433
55443
|
try {
|
|
@@ -57752,7 +57762,7 @@ async function initAction(options, simulatorService) {
|
|
|
57752
57762
|
{
|
|
57753
57763
|
type: "confirm",
|
|
57754
57764
|
name: "confirmReset",
|
|
57755
|
-
message: `This command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, and
|
|
57765
|
+
message: `This command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?`,
|
|
57756
57766
|
default: true
|
|
57757
57767
|
}
|
|
57758
57768
|
]);
|
|
@@ -57948,10 +57958,53 @@ async function startAction(options, simulatorService) {
|
|
|
57948
57958
|
}
|
|
57949
57959
|
}
|
|
57950
57960
|
|
|
57961
|
+
// src/lib/actions/BaseAction.ts
|
|
57962
|
+
var BaseAction = class {
|
|
57963
|
+
async confirmPrompt(message) {
|
|
57964
|
+
const answer = await lib_default.prompt([
|
|
57965
|
+
{
|
|
57966
|
+
type: "confirm",
|
|
57967
|
+
name: "confirmAction",
|
|
57968
|
+
message,
|
|
57969
|
+
default: true
|
|
57970
|
+
}
|
|
57971
|
+
]);
|
|
57972
|
+
if (!answer.confirmAction) {
|
|
57973
|
+
console.log("Operation aborted!");
|
|
57974
|
+
process.exit(0);
|
|
57975
|
+
}
|
|
57976
|
+
}
|
|
57977
|
+
};
|
|
57978
|
+
|
|
57979
|
+
// src/commands/general/stop.ts
|
|
57980
|
+
var StopAction = class extends BaseAction {
|
|
57981
|
+
constructor() {
|
|
57982
|
+
super();
|
|
57983
|
+
__publicField(this, "simulatorService");
|
|
57984
|
+
this.simulatorService = new SimulatorService();
|
|
57985
|
+
}
|
|
57986
|
+
async stop() {
|
|
57987
|
+
try {
|
|
57988
|
+
await this.confirmPrompt(
|
|
57989
|
+
"Are you sure you want to stop all running GenLayer containers? This will halt all active processes."
|
|
57990
|
+
);
|
|
57991
|
+
console.log(`Stopping Docker containers...`);
|
|
57992
|
+
await this.simulatorService.stopDockerContainers();
|
|
57993
|
+
console.log(`All running GenLayer containers have been successfully stopped.`);
|
|
57994
|
+
} catch (error) {
|
|
57995
|
+
console.error("An error occurred while stopping the containers:", error);
|
|
57996
|
+
}
|
|
57997
|
+
}
|
|
57998
|
+
};
|
|
57999
|
+
|
|
57951
58000
|
// src/commands/general/index.ts
|
|
57952
58001
|
function initializeGeneralCommands(program2) {
|
|
57953
58002
|
program2.command("init").description("Initialize the GenLayer Environment").option("--numValidators <numValidators>", "Number of validators", "5").option("--headless", "Headless mode", false).option("--reset-db", "Reset Database", false).option("--localnet-version <localnetVersion>", "Select a specific localnet version", localnetCompatibleVersion).action((options) => initAction(options, simulator_default));
|
|
57954
58003
|
program2.command("up").description("Starts GenLayer's simulator").option("--reset-validators", "Remove all current validators and create new random ones", false).option("--numValidators <numValidators>", "Number of validators", "5").option("--headless", "Headless mode", false).option("--reset-db", "Reset Database", false).action((options) => startAction(options, simulator_default));
|
|
58004
|
+
program2.command("stop").description("Stop all running localnet services.").action(async () => {
|
|
58005
|
+
const stopAction = new StopAction();
|
|
58006
|
+
await stopAction.stop();
|
|
58007
|
+
});
|
|
57955
58008
|
return program2;
|
|
57956
58009
|
}
|
|
57957
58010
|
|
|
@@ -86824,24 +86877,6 @@ function initializeConfigCommands(program2) {
|
|
|
86824
86877
|
return program2;
|
|
86825
86878
|
}
|
|
86826
86879
|
|
|
86827
|
-
// src/lib/actions/BaseAction.ts
|
|
86828
|
-
var BaseAction = class {
|
|
86829
|
-
async confirmPrompt(message) {
|
|
86830
|
-
const answer = await lib_default.prompt([
|
|
86831
|
-
{
|
|
86832
|
-
type: "confirm",
|
|
86833
|
-
name: "confirmAction",
|
|
86834
|
-
message,
|
|
86835
|
-
default: true
|
|
86836
|
-
}
|
|
86837
|
-
]);
|
|
86838
|
-
if (!answer.confirmAction) {
|
|
86839
|
-
console.log("Operation aborted!");
|
|
86840
|
-
process.exit(0);
|
|
86841
|
-
}
|
|
86842
|
-
}
|
|
86843
|
-
};
|
|
86844
|
-
|
|
86845
86880
|
// src/commands/validators/validators.ts
|
|
86846
86881
|
var ValidatorsAction = class extends BaseAction {
|
|
86847
86882
|
async getValidator(options) {
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import simulatorService from "../../lib/services/simulator";
|
|
|
4
4
|
import { initAction, InitActionOptions } from "./init";
|
|
5
5
|
import { startAction, StartActionOptions } from "./start";
|
|
6
6
|
import {localnetCompatibleVersion} from "../../lib/config/simulator";
|
|
7
|
+
import {StopAction} from "./stop";
|
|
7
8
|
|
|
8
9
|
export function initializeGeneralCommands(program: Command) {
|
|
9
10
|
program
|
|
@@ -24,5 +25,13 @@ export function initializeGeneralCommands(program: Command) {
|
|
|
24
25
|
.option("--reset-db", "Reset Database", false)
|
|
25
26
|
.action((options: StartActionOptions) => startAction(options, simulatorService));
|
|
26
27
|
|
|
28
|
+
program
|
|
29
|
+
.command("stop")
|
|
30
|
+
.description("Stop all running localnet services.")
|
|
31
|
+
.action(async () => {
|
|
32
|
+
const stopAction = new StopAction();
|
|
33
|
+
await stopAction.stop();
|
|
34
|
+
});
|
|
35
|
+
|
|
27
36
|
return program;
|
|
28
37
|
}
|
|
@@ -77,7 +77,7 @@ export async function initAction(options: InitActionOptions, simulatorService: I
|
|
|
77
77
|
{
|
|
78
78
|
type: "confirm",
|
|
79
79
|
name: "confirmReset",
|
|
80
|
-
message: `This command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, and
|
|
80
|
+
message: `This command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?`,
|
|
81
81
|
default: true,
|
|
82
82
|
},
|
|
83
83
|
]);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseAction } from "../../lib/actions/BaseAction";
|
|
2
|
+
import { SimulatorService } from "../../lib/services/simulator";
|
|
3
|
+
import { ISimulatorService } from "../../lib/interfaces/ISimulatorService";
|
|
4
|
+
|
|
5
|
+
export class StopAction extends BaseAction {
|
|
6
|
+
private simulatorService: ISimulatorService;
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
this.simulatorService = new SimulatorService();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async stop(): Promise<void> {
|
|
14
|
+
try{
|
|
15
|
+
await this.confirmPrompt(
|
|
16
|
+
"Are you sure you want to stop all running GenLayer containers? This will halt all active processes."
|
|
17
|
+
);
|
|
18
|
+
console.log(`Stopping Docker containers...`);
|
|
19
|
+
await this.simulatorService.stopDockerContainers();
|
|
20
|
+
console.log(`All running GenLayer containers have been successfully stopped.`);
|
|
21
|
+
}catch (error) {
|
|
22
|
+
console.error("An error occurred while stopping the containers:", error)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -12,8 +12,9 @@ export interface ISimulatorService {
|
|
|
12
12
|
getAiProvidersOptions(withHint: boolean): Array<{name: string; value: string}>;
|
|
13
13
|
getFrontendUrl(): string;
|
|
14
14
|
openFrontend(): Promise<boolean>;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
stopDockerContainers(): Promise<void>;
|
|
16
|
+
resetDockerContainers(): Promise<void>;
|
|
17
|
+
resetDockerImages(): Promise<void>;
|
|
17
18
|
checkCliVersion(): Promise<void>;
|
|
18
19
|
cleanDatabase(): Promise<boolean>;
|
|
19
20
|
addConfigToEnvFile(newConfig: Record<string, string>): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Docker from "dockerode"
|
|
1
|
+
import Docker, {ContainerInfo} from "dockerode";
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as dotenv from "dotenv";
|
|
4
4
|
import * as path from "path";
|
|
@@ -48,6 +48,39 @@ export class SimulatorService implements ISimulatorService {
|
|
|
48
48
|
this.docker = new Docker();
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
private readEnvConfigValue(key: string): string {
|
|
52
|
+
const envFilePath = path.join(this.location, ".env");
|
|
53
|
+
// Transform the config string to object
|
|
54
|
+
const envConfig = dotenv.parse(fs.readFileSync(envFilePath, "utf8"));
|
|
55
|
+
return envConfig[key];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private async getGenlayerContainers(): Promise<ContainerInfo[]> {
|
|
59
|
+
const containers = await this.docker.listContainers({ all: true });
|
|
60
|
+
return containers.filter(container =>
|
|
61
|
+
container.Names.some(name =>
|
|
62
|
+
name.startsWith(CONTAINERS_NAME_PREFIX) || name.includes("ollama")
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private async stopAndRemoveContainers(remove: boolean = false): Promise<void> {
|
|
68
|
+
const genlayerContainers = await this.getGenlayerContainers();
|
|
69
|
+
|
|
70
|
+
for (const containerInfo of genlayerContainers) {
|
|
71
|
+
const container = this.docker.getContainer(containerInfo.Id);
|
|
72
|
+
if (containerInfo.State === "running") {
|
|
73
|
+
await container.stop();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const isOllamaContainer = containerInfo.Names.some(name => name.includes("ollama"));
|
|
77
|
+
|
|
78
|
+
if (remove && !isOllamaContainer) {
|
|
79
|
+
await container.remove();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
51
84
|
public addConfigToEnvFile(newConfig: Record<string, string>): void {
|
|
52
85
|
const envFilePath = path.join(this.location, ".env");
|
|
53
86
|
|
|
@@ -76,13 +109,6 @@ export class SimulatorService implements ISimulatorService {
|
|
|
76
109
|
return this.composeOptions;
|
|
77
110
|
}
|
|
78
111
|
|
|
79
|
-
private readEnvConfigValue(key: string): string {
|
|
80
|
-
const envFilePath = path.join(this.location, ".env");
|
|
81
|
-
// Transform the config string to object
|
|
82
|
-
const envConfig = dotenv.parse(fs.readFileSync(envFilePath, "utf8"));
|
|
83
|
-
return envConfig[key];
|
|
84
|
-
}
|
|
85
|
-
|
|
86
112
|
public async checkCliVersion(): Promise<void> {
|
|
87
113
|
const update = await updateCheck(pkg);
|
|
88
114
|
if (update && update.latest !== pkg.version) {
|
|
@@ -218,25 +244,15 @@ export class SimulatorService implements ISimulatorService {
|
|
|
218
244
|
return true;
|
|
219
245
|
}
|
|
220
246
|
|
|
221
|
-
public async
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
container.Names.some(name =>
|
|
225
|
-
name.startsWith(CONTAINERS_NAME_PREFIX)
|
|
226
|
-
)
|
|
227
|
-
);
|
|
247
|
+
public async stopDockerContainers(): Promise<void> {
|
|
248
|
+
await this.stopAndRemoveContainers(false);
|
|
249
|
+
}
|
|
228
250
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (containerInfo.State === "running") {
|
|
232
|
-
await container.stop();
|
|
233
|
-
}
|
|
234
|
-
await container.remove();
|
|
235
|
-
}
|
|
236
|
-
return true;
|
|
251
|
+
public async resetDockerContainers(): Promise<void> {
|
|
252
|
+
await this.stopAndRemoveContainers(true);
|
|
237
253
|
}
|
|
238
254
|
|
|
239
|
-
public async resetDockerImages(): Promise<
|
|
255
|
+
public async resetDockerImages(): Promise<void> {
|
|
240
256
|
const images = await this.docker.listImages();
|
|
241
257
|
const genlayerImages = images.filter(image =>
|
|
242
258
|
image.RepoTags?.some(tag => tag.startsWith(IMAGES_NAME_PREFIX))
|
|
@@ -246,8 +262,6 @@ export class SimulatorService implements ISimulatorService {
|
|
|
246
262
|
const image = this.docker.getImage(imageInfo.Id);
|
|
247
263
|
await image.remove({force: true});
|
|
248
264
|
}
|
|
249
|
-
|
|
250
|
-
return true;
|
|
251
265
|
}
|
|
252
266
|
|
|
253
267
|
public async cleanDatabase(): Promise<boolean> {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, test, vi, beforeEach, afterEach, expect } from "vitest";
|
|
2
|
+
import { StopAction } from "../../src/commands/general/stop";
|
|
3
|
+
import { SimulatorService } from "../../src/lib/services/simulator";
|
|
4
|
+
import { ISimulatorService } from "../../src/lib/interfaces/ISimulatorService";
|
|
5
|
+
import inquirer from "inquirer";
|
|
6
|
+
|
|
7
|
+
vi.mock("../../src/lib/services/simulator");
|
|
8
|
+
vi.mock("inquirer");
|
|
9
|
+
|
|
10
|
+
describe("StopAction", () => {
|
|
11
|
+
let stopAction: StopAction;
|
|
12
|
+
let mockSimulatorService: ISimulatorService;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
vi.clearAllMocks();
|
|
16
|
+
|
|
17
|
+
mockSimulatorService = {
|
|
18
|
+
stopDockerContainers: vi.fn(),
|
|
19
|
+
} as unknown as ISimulatorService;
|
|
20
|
+
|
|
21
|
+
SimulatorService.prototype.stopDockerContainers = mockSimulatorService.stopDockerContainers;
|
|
22
|
+
|
|
23
|
+
stopAction = new StopAction();
|
|
24
|
+
(stopAction as any).simulatorService = mockSimulatorService;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
vi.restoreAllMocks();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("should stop containers if user confirms", async () => {
|
|
32
|
+
vi.mocked(inquirer.prompt).mockResolvedValue({ confirmAction: true });
|
|
33
|
+
|
|
34
|
+
await stopAction.stop();
|
|
35
|
+
|
|
36
|
+
expect(inquirer.prompt).toHaveBeenCalledWith([
|
|
37
|
+
{
|
|
38
|
+
type: "confirm",
|
|
39
|
+
name: "confirmAction",
|
|
40
|
+
message: "Are you sure you want to stop all running GenLayer containers? This will halt all active processes.",
|
|
41
|
+
default: true,
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
expect(mockSimulatorService.stopDockerContainers).toHaveBeenCalled();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("should abort if user cancels", async () => {
|
|
48
|
+
vi.mocked(inquirer.prompt).mockResolvedValue({ confirmAction: false });
|
|
49
|
+
|
|
50
|
+
console.log = vi.fn();
|
|
51
|
+
|
|
52
|
+
await stopAction.stop();
|
|
53
|
+
|
|
54
|
+
expect(inquirer.prompt).toHaveBeenCalled();
|
|
55
|
+
expect(console.log).toHaveBeenCalledWith("Operation aborted!");
|
|
56
|
+
expect(mockSimulatorService.stopDockerContainers).not.toHaveBeenCalled();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { vi, describe, beforeEach, afterEach, test, expect } from "vitest";
|
|
3
|
+
import { initializeGeneralCommands } from "../../src/commands/general";
|
|
4
|
+
import { StopAction } from "../../src/commands/general/stop";
|
|
5
|
+
|
|
6
|
+
vi.mock("../../src/commands/general/stop");
|
|
7
|
+
|
|
8
|
+
describe("stop command", () => {
|
|
9
|
+
let program: Command;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
program = new Command();
|
|
13
|
+
initializeGeneralCommands(program);
|
|
14
|
+
|
|
15
|
+
vi.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
vi.restoreAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("doesn't require arguments or options", async () => {
|
|
23
|
+
expect(() => program.parse(["node", "test", "stop"])).not.toThrow();
|
|
24
|
+
expect(StopAction).toHaveBeenCalledTimes(1);
|
|
25
|
+
expect(StopAction.prototype.stop).toHaveBeenCalledWith();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -329,7 +329,7 @@ describe("SimulatorService - Docker Tests", () => {
|
|
|
329
329
|
|
|
330
330
|
const result = await simulatorService.resetDockerContainers();
|
|
331
331
|
|
|
332
|
-
expect(result).toBe(
|
|
332
|
+
expect(result).toBe(undefined);
|
|
333
333
|
expect(mockListContainers).toHaveBeenCalledWith({ all: true });
|
|
334
334
|
|
|
335
335
|
// Ensure only the relevant containers were stopped and removed
|
|
@@ -341,6 +341,36 @@ describe("SimulatorService - Docker Tests", () => {
|
|
|
341
341
|
expect(mockRemove).toHaveBeenCalledTimes(2);
|
|
342
342
|
});
|
|
343
343
|
|
|
344
|
+
test("should stop all running GenLayer containers", async () => {
|
|
345
|
+
const mockContainers = [
|
|
346
|
+
{
|
|
347
|
+
Id: "container1",
|
|
348
|
+
Names: [`${CONTAINERS_NAME_PREFIX}container1`],
|
|
349
|
+
State: "running",
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
Id: "container2",
|
|
353
|
+
Names: [`${CONTAINERS_NAME_PREFIX}container2`],
|
|
354
|
+
State: "exited",
|
|
355
|
+
},
|
|
356
|
+
];
|
|
357
|
+
|
|
358
|
+
vi.mocked(Docker.prototype.listContainers).mockResolvedValue(mockContainers as any);
|
|
359
|
+
|
|
360
|
+
const mockStop = vi.fn().mockResolvedValue(undefined);
|
|
361
|
+
const mockGetContainer = vi.mocked(Docker.prototype.getContainer);
|
|
362
|
+
mockGetContainer.mockImplementation(() => ({
|
|
363
|
+
stop: mockStop,
|
|
364
|
+
} as unknown as Docker.Container));
|
|
365
|
+
|
|
366
|
+
await simulatorService.stopDockerContainers();
|
|
367
|
+
|
|
368
|
+
expect(mockGetContainer).toHaveBeenCalledWith("container1");
|
|
369
|
+
expect(mockGetContainer).toHaveBeenCalledWith("container2");
|
|
370
|
+
expect(mockStop).toHaveBeenCalledTimes(1);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
|
|
344
374
|
test("should remove Docker images with the specified prefix", async () => {
|
|
345
375
|
const mockImages = [
|
|
346
376
|
{
|
|
@@ -366,7 +396,7 @@ describe("SimulatorService - Docker Tests", () => {
|
|
|
366
396
|
|
|
367
397
|
const result = await simulatorService.resetDockerImages();
|
|
368
398
|
|
|
369
|
-
expect(result).toBe(
|
|
399
|
+
expect(result).toBe(undefined);
|
|
370
400
|
expect(mockListImages).toHaveBeenCalled();
|
|
371
401
|
expect(mockGetImage).toHaveBeenCalledWith("image1");
|
|
372
402
|
expect(mockGetImage).toHaveBeenCalledWith("image2");
|