@docker-digital/dockernet-agent 0.0.1
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/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/agent/agent.module.d.ts +2 -0
- package/dist/agent/agent.module.js +47 -0
- package/dist/agent/agent.module.js.map +1 -0
- package/dist/agent/commands/agent.command.d.ts +58 -0
- package/dist/agent/commands/agent.command.js +417 -0
- package/dist/agent/commands/agent.command.js.map +1 -0
- package/dist/agent/services/api.service.d.ts +13 -0
- package/dist/agent/services/api.service.js +116 -0
- package/dist/agent/services/api.service.js.map +1 -0
- package/dist/agent/services/config.service.d.ts +28 -0
- package/dist/agent/services/config.service.js +100 -0
- package/dist/agent/services/config.service.js.map +1 -0
- package/dist/agent/services/docker-event.service.d.ts +44 -0
- package/dist/agent/services/docker-event.service.js +141 -0
- package/dist/agent/services/docker-event.service.js.map +1 -0
- package/dist/agent/services/docker.service.d.ts +16 -0
- package/dist/agent/services/docker.service.js +170 -0
- package/dist/agent/services/docker.service.js.map +1 -0
- package/dist/agent/services/event-websocket-client.service.d.ts +49 -0
- package/dist/agent/services/event-websocket-client.service.js +248 -0
- package/dist/agent/services/event-websocket-client.service.js.map +1 -0
- package/dist/agent/services/event.service.d.ts +27 -0
- package/dist/agent/services/event.service.js +242 -0
- package/dist/agent/services/event.service.js.map +1 -0
- package/dist/agent/services/log.service.d.ts +19 -0
- package/dist/agent/services/log.service.js +176 -0
- package/dist/agent/services/log.service.js.map +1 -0
- package/dist/agent/services/machine.service.d.ts +15 -0
- package/dist/agent/services/machine.service.js +148 -0
- package/dist/agent/services/machine.service.js.map +1 -0
- package/dist/agent/services/profile.service.d.ts +33 -0
- package/dist/agent/services/profile.service.js +438 -0
- package/dist/agent/services/profile.service.js.map +1 -0
- package/dist/agent/services/volume-sync.service.d.ts +9 -0
- package/dist/agent/services/volume-sync.service.js +87 -0
- package/dist/agent/services/volume-sync.service.js.map +1 -0
- package/dist/agent/services/websocket-client.service.d.ts +48 -0
- package/dist/agent/services/websocket-client.service.js +278 -0
- package/dist/agent/services/websocket-client.service.js.map +1 -0
- package/dist/app.module.d.ts +2 -0
- package/dist/app.module.js +31 -0
- package/dist/app.module.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +12 -0
- package/dist/main.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +103 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 DockerNet
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# DockerNet Agent
|
|
2
|
+
|
|
3
|
+
NestJS-based agent application for DockerNet system.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Global Installation (Recommended)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @dockernet/agent
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Sau khi cài đặt, bạn có thể chạy `agent` hoặc `dockernet-agent` từ bất kỳ đâu:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Set API key
|
|
17
|
+
agent --apiKey YOUR_API_KEY
|
|
18
|
+
|
|
19
|
+
# Show config
|
|
20
|
+
agent --config
|
|
21
|
+
|
|
22
|
+
# List profiles
|
|
23
|
+
agent --profiles
|
|
24
|
+
|
|
25
|
+
# Run as daemon
|
|
26
|
+
agent --run
|
|
27
|
+
|
|
28
|
+
# Stop daemon
|
|
29
|
+
agent --stop
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Local Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### CLI Commands (After Global Installation)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Set API key
|
|
44
|
+
agent --apiKey YOUR_API_KEY
|
|
45
|
+
|
|
46
|
+
# Show config
|
|
47
|
+
agent --config
|
|
48
|
+
|
|
49
|
+
# List profiles
|
|
50
|
+
agent --profiles
|
|
51
|
+
|
|
52
|
+
# Show version
|
|
53
|
+
agent --version
|
|
54
|
+
|
|
55
|
+
# Run as daemon
|
|
56
|
+
agent --run
|
|
57
|
+
|
|
58
|
+
# Stop daemon
|
|
59
|
+
agent --stop
|
|
60
|
+
|
|
61
|
+
# Restart daemon
|
|
62
|
+
agent --restart
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Local Development Commands
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Set API key
|
|
69
|
+
npm run agent -- --apiKey YOUR_API_KEY
|
|
70
|
+
|
|
71
|
+
# Show config
|
|
72
|
+
npm run agent -- --config
|
|
73
|
+
|
|
74
|
+
# List profiles
|
|
75
|
+
npm run agent -- --profiles
|
|
76
|
+
|
|
77
|
+
# Run as daemon
|
|
78
|
+
npm run agent -- --run
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Development
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Run in development mode
|
|
85
|
+
npm run dev
|
|
86
|
+
|
|
87
|
+
# Build
|
|
88
|
+
npm run build
|
|
89
|
+
|
|
90
|
+
# Run production build
|
|
91
|
+
npm run start:prod
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Architecture
|
|
95
|
+
|
|
96
|
+
The agent is structured following NestJS best practices:
|
|
97
|
+
|
|
98
|
+
- **Services**: Core business logic
|
|
99
|
+
- `ApiService`: HTTP client for backend API
|
|
100
|
+
- `ConfigService`: Configuration management
|
|
101
|
+
- `DockerService`: Docker operations
|
|
102
|
+
- `EventService`: Event polling and processing
|
|
103
|
+
- `LogService`: Container log streaming
|
|
104
|
+
- `MachineService`: Machine registration and status
|
|
105
|
+
- `ProfileService`: Profile management (start/stop)
|
|
106
|
+
- `VolumeSyncService`: Volume synchronization
|
|
107
|
+
|
|
108
|
+
- **Commands**: CLI interface
|
|
109
|
+
- `AgentCommand`: Main command handler
|
|
110
|
+
|
|
111
|
+
## Features
|
|
112
|
+
|
|
113
|
+
- Machine registration with server
|
|
114
|
+
- Event polling and processing
|
|
115
|
+
- Profile start/stop operations
|
|
116
|
+
- Container log streaming
|
|
117
|
+
- Service status updates
|
|
118
|
+
- Volume synchronization
|
|
119
|
+
- Private registry authentication
|
|
120
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.AgentModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const config_1 = require("@nestjs/config");
|
|
12
|
+
const agent_command_1 = require("./commands/agent.command");
|
|
13
|
+
const api_service_1 = require("./services/api.service");
|
|
14
|
+
const config_service_1 = require("./services/config.service");
|
|
15
|
+
const docker_service_1 = require("./services/docker.service");
|
|
16
|
+
const docker_event_service_1 = require("./services/docker-event.service");
|
|
17
|
+
const event_service_1 = require("./services/event.service");
|
|
18
|
+
const log_service_1 = require("./services/log.service");
|
|
19
|
+
const machine_service_1 = require("./services/machine.service");
|
|
20
|
+
const profile_service_1 = require("./services/profile.service");
|
|
21
|
+
const volume_sync_service_1 = require("./services/volume-sync.service");
|
|
22
|
+
const websocket_client_service_1 = require("./services/websocket-client.service");
|
|
23
|
+
const event_websocket_client_service_1 = require("./services/event-websocket-client.service");
|
|
24
|
+
let AgentModule = class AgentModule {
|
|
25
|
+
};
|
|
26
|
+
exports.AgentModule = AgentModule;
|
|
27
|
+
exports.AgentModule = AgentModule = __decorate([
|
|
28
|
+
(0, common_1.Module)({
|
|
29
|
+
imports: [config_1.ConfigModule],
|
|
30
|
+
providers: [
|
|
31
|
+
agent_command_1.AgentCommand,
|
|
32
|
+
api_service_1.ApiService,
|
|
33
|
+
config_service_1.ConfigService,
|
|
34
|
+
docker_service_1.DockerService,
|
|
35
|
+
docker_event_service_1.DockerEventService,
|
|
36
|
+
event_service_1.EventService,
|
|
37
|
+
log_service_1.LogService,
|
|
38
|
+
machine_service_1.MachineService,
|
|
39
|
+
profile_service_1.ProfileService,
|
|
40
|
+
volume_sync_service_1.VolumeSyncService,
|
|
41
|
+
websocket_client_service_1.WebSocketClientService,
|
|
42
|
+
event_websocket_client_service_1.EventWebSocketClientService,
|
|
43
|
+
],
|
|
44
|
+
exports: [agent_command_1.AgentCommand],
|
|
45
|
+
})
|
|
46
|
+
], AgentModule);
|
|
47
|
+
//# sourceMappingURL=agent.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.module.js","sourceRoot":"","sources":["../../src/agent/agent.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2CAA8C;AAC9C,4DAAwD;AACxD,wDAAoD;AACpD,8DAA0D;AAC1D,8DAA0D;AAC1D,0EAAqE;AACrE,4DAAwD;AACxD,wDAAoD;AACpD,gEAA4D;AAC5D,gEAA4D;AAC5D,wEAAmE;AACnE,kFAA6E;AAC7E,8FAAwF;AAoBjF,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IAlBvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAY,CAAC;QACvB,SAAS,EAAE;YACT,4BAAY;YACZ,wBAAU;YACV,8BAAa;YACb,8BAAa;YACb,yCAAkB;YAClB,4BAAY;YACZ,wBAAU;YACV,gCAAc;YACd,gCAAc;YACd,uCAAiB;YACjB,iDAAsB;YACtB,4DAA2B;SAC5B;QACD,OAAO,EAAE,CAAC,4BAAY,CAAC;KACxB,CAAC;GACW,WAAW,CAAG"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { CommandRunner } from 'nest-commander';
|
|
3
|
+
import { ApiService } from '../services/api.service';
|
|
4
|
+
import { ConfigService } from '../services/config.service';
|
|
5
|
+
import { DockerService } from '../services/docker.service';
|
|
6
|
+
import { EventService } from '../services/event.service';
|
|
7
|
+
import { LogService } from '../services/log.service';
|
|
8
|
+
import { MachineService } from '../services/machine.service';
|
|
9
|
+
import { ProfileService } from '../services/profile.service';
|
|
10
|
+
import { VolumeSyncService } from '../services/volume-sync.service';
|
|
11
|
+
import { WebSocketClientService } from '../services/websocket-client.service';
|
|
12
|
+
interface AgentCommandOptions {
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
config?: boolean;
|
|
15
|
+
profiles?: boolean;
|
|
16
|
+
upgrade?: boolean;
|
|
17
|
+
log?: boolean;
|
|
18
|
+
version?: boolean;
|
|
19
|
+
run?: boolean;
|
|
20
|
+
stop?: boolean;
|
|
21
|
+
restart?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare class AgentCommand extends CommandRunner implements OnModuleInit {
|
|
24
|
+
private apiService;
|
|
25
|
+
private configService;
|
|
26
|
+
private dockerService;
|
|
27
|
+
private eventService;
|
|
28
|
+
private logService;
|
|
29
|
+
private machineService;
|
|
30
|
+
private profileService;
|
|
31
|
+
private volumeSyncService;
|
|
32
|
+
private websocketClientService;
|
|
33
|
+
private readonly logger;
|
|
34
|
+
private isRunning;
|
|
35
|
+
constructor(apiService: ApiService, configService: ConfigService, dockerService: DockerService, eventService: EventService, logService: LogService, machineService: MachineService, profileService: ProfileService, volumeSyncService: VolumeSyncService, websocketClientService: WebSocketClientService);
|
|
36
|
+
onModuleInit(): Promise<void>;
|
|
37
|
+
run(passedParams: string[], options?: AgentCommandOptions): Promise<void>;
|
|
38
|
+
parseApiKey(val: string): string;
|
|
39
|
+
parseConfig(): boolean;
|
|
40
|
+
parseProfiles(): boolean;
|
|
41
|
+
parseUpgrade(): boolean;
|
|
42
|
+
parseLog(): boolean;
|
|
43
|
+
parseVersion(): boolean;
|
|
44
|
+
parseRun(): boolean;
|
|
45
|
+
parseStop(): boolean;
|
|
46
|
+
parseRestart(): boolean;
|
|
47
|
+
private handleApiKey;
|
|
48
|
+
private handleConfig;
|
|
49
|
+
private handleProfiles;
|
|
50
|
+
private handleUpgrade;
|
|
51
|
+
private handleLog;
|
|
52
|
+
private handleVersion;
|
|
53
|
+
private handleStop;
|
|
54
|
+
private handleRestart;
|
|
55
|
+
private printUsage;
|
|
56
|
+
runDaemon(): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var AgentCommand_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.AgentCommand = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const nest_commander_1 = require("nest-commander");
|
|
16
|
+
const fs = require("fs-extra");
|
|
17
|
+
const path = require("path");
|
|
18
|
+
const api_service_1 = require("../services/api.service");
|
|
19
|
+
const config_service_1 = require("../services/config.service");
|
|
20
|
+
const docker_service_1 = require("../services/docker.service");
|
|
21
|
+
const event_service_1 = require("../services/event.service");
|
|
22
|
+
const log_service_1 = require("../services/log.service");
|
|
23
|
+
const machine_service_1 = require("../services/machine.service");
|
|
24
|
+
const profile_service_1 = require("../services/profile.service");
|
|
25
|
+
const volume_sync_service_1 = require("../services/volume-sync.service");
|
|
26
|
+
const websocket_client_service_1 = require("../services/websocket-client.service");
|
|
27
|
+
let AgentCommand = AgentCommand_1 = class AgentCommand extends nest_commander_1.CommandRunner {
|
|
28
|
+
constructor(apiService, configService, dockerService, eventService, logService, machineService, profileService, volumeSyncService, websocketClientService) {
|
|
29
|
+
super();
|
|
30
|
+
this.apiService = apiService;
|
|
31
|
+
this.configService = configService;
|
|
32
|
+
this.dockerService = dockerService;
|
|
33
|
+
this.eventService = eventService;
|
|
34
|
+
this.logService = logService;
|
|
35
|
+
this.machineService = machineService;
|
|
36
|
+
this.profileService = profileService;
|
|
37
|
+
this.volumeSyncService = volumeSyncService;
|
|
38
|
+
this.websocketClientService = websocketClientService;
|
|
39
|
+
this.logger = new common_1.Logger(AgentCommand_1.name);
|
|
40
|
+
this.isRunning = false;
|
|
41
|
+
}
|
|
42
|
+
async onModuleInit() {
|
|
43
|
+
await this.apiService.initialize();
|
|
44
|
+
}
|
|
45
|
+
async run(passedParams, options) {
|
|
46
|
+
if (options?.apiKey) {
|
|
47
|
+
await this.handleApiKey(options.apiKey);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (options?.config) {
|
|
51
|
+
await this.handleConfig();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (options?.profiles) {
|
|
55
|
+
await this.handleProfiles();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (options?.upgrade) {
|
|
59
|
+
await this.handleUpgrade();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (options?.log) {
|
|
63
|
+
await this.handleLog();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (options?.version) {
|
|
67
|
+
this.handleVersion();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (options?.stop) {
|
|
71
|
+
await this.handleStop();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (options?.restart) {
|
|
75
|
+
await this.handleRestart();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (!options || Object.keys(options).length === 0) {
|
|
79
|
+
if (passedParams.length === 0) {
|
|
80
|
+
this.handleVersion();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (options?.run) {
|
|
85
|
+
await this.runDaemon();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.printUsage();
|
|
89
|
+
}
|
|
90
|
+
parseApiKey(val) {
|
|
91
|
+
return val;
|
|
92
|
+
}
|
|
93
|
+
parseConfig() {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
parseProfiles() {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
parseUpgrade() {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
parseLog() {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
parseVersion() {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
parseRun() {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
parseStop() {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
parseRestart() {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
async handleApiKey(apiKey) {
|
|
118
|
+
if (!apiKey) {
|
|
119
|
+
console.error('API key is required');
|
|
120
|
+
console.error('Example: agent --apiKey YOUR_API_KEY');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
const existing = await this.configService.loadConfig();
|
|
124
|
+
const machineKey = existing.machineKey || this.machineService.generateMachineKey();
|
|
125
|
+
if (!existing.machineKey) {
|
|
126
|
+
console.log(`Generated new MACHINE_KEY: ${machineKey}`);
|
|
127
|
+
}
|
|
128
|
+
await this.configService.saveConfig({
|
|
129
|
+
apiKey,
|
|
130
|
+
machineKey,
|
|
131
|
+
serverUrl: existing.serverUrl,
|
|
132
|
+
});
|
|
133
|
+
await this.apiService.setApiKey(apiKey);
|
|
134
|
+
console.log(`API key saved to ${this.configService.configFilePath}`);
|
|
135
|
+
process.exit(0);
|
|
136
|
+
}
|
|
137
|
+
async handleConfig() {
|
|
138
|
+
const config = await this.configService.loadConfig();
|
|
139
|
+
console.log(`Config file : ${this.configService.configFilePath}`);
|
|
140
|
+
console.log(`SERVER_URL : ${this.configService.serverUrl}`);
|
|
141
|
+
console.log(`MACHINE_KEY : ${config.machineKey || '<not set>'}`);
|
|
142
|
+
if (config.apiKey) {
|
|
143
|
+
console.log(`API_KEY : (set, value hidden)`);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
console.log(`API_KEY : <not set>`);
|
|
147
|
+
}
|
|
148
|
+
process.exit(0);
|
|
149
|
+
}
|
|
150
|
+
async handleProfiles() {
|
|
151
|
+
const workDir = this.configService.workDirPath;
|
|
152
|
+
const profiles = await fs.readdir(workDir);
|
|
153
|
+
console.log(`Profiles in ${workDir}:`);
|
|
154
|
+
console.log(`${'PROFILE_ID'.padEnd(30)} | ${'WORKSPACE_ID'.padEnd(36)} | ${'RUNNING'.padEnd(10)}`);
|
|
155
|
+
console.log('-'.repeat(80));
|
|
156
|
+
let found = 0;
|
|
157
|
+
for (const profileId of profiles) {
|
|
158
|
+
const profileDir = path.join(workDir, profileId);
|
|
159
|
+
if (!(await fs.stat(profileDir)).isDirectory()) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
found++;
|
|
163
|
+
const metadataFile = path.join(profileDir, '.profile_metadata');
|
|
164
|
+
let workspaceId = '<unknown>';
|
|
165
|
+
let running = 'no';
|
|
166
|
+
if (await fs.pathExists(metadataFile)) {
|
|
167
|
+
const metadata = await fs.readFile(metadataFile, 'utf-8');
|
|
168
|
+
const match = metadata.match(/^workspace_id=(.+)$/m);
|
|
169
|
+
if (match) {
|
|
170
|
+
workspaceId = match[1].trim();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const composeFile = path.join(profileDir, `docker-compose_${profileId}.yaml`);
|
|
174
|
+
if (await fs.pathExists(composeFile)) {
|
|
175
|
+
running = 'yes';
|
|
176
|
+
}
|
|
177
|
+
console.log(`${profileId.padEnd(30)} | ${workspaceId.padEnd(36)} | ${running.padEnd(10)}`);
|
|
178
|
+
}
|
|
179
|
+
if (found === 0) {
|
|
180
|
+
console.log(`(no profiles found in ${workDir})`);
|
|
181
|
+
}
|
|
182
|
+
process.exit(0);
|
|
183
|
+
}
|
|
184
|
+
async handleUpgrade() {
|
|
185
|
+
const scriptUrl = `${this.configService.apiBaseUrl}/script`;
|
|
186
|
+
console.log(`Downloading latest agent from: ${scriptUrl}`);
|
|
187
|
+
console.log('Upgrade functionality to be implemented');
|
|
188
|
+
process.exit(0);
|
|
189
|
+
}
|
|
190
|
+
async handleLog() {
|
|
191
|
+
const logFile = this.configService.logFilePath;
|
|
192
|
+
if (await fs.pathExists(logFile)) {
|
|
193
|
+
console.log(`Following log from ${logFile}:`);
|
|
194
|
+
console.log('Press Ctrl+C to stop.');
|
|
195
|
+
console.log('Log viewing functionality to be implemented');
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
console.log(`No log file found at ${logFile}`);
|
|
199
|
+
console.log('Suggestion: run agent as daemon with: agent --run');
|
|
200
|
+
}
|
|
201
|
+
process.exit(0);
|
|
202
|
+
}
|
|
203
|
+
handleVersion() {
|
|
204
|
+
console.log('DockerNet Agent version 0.1.2');
|
|
205
|
+
process.exit(0);
|
|
206
|
+
}
|
|
207
|
+
async handleStop() {
|
|
208
|
+
const pidFile = this.configService.pidFilePath;
|
|
209
|
+
if (await fs.pathExists(pidFile)) {
|
|
210
|
+
const pid = parseInt(await fs.readFile(pidFile, 'utf-8'), 10);
|
|
211
|
+
if (pid && !isNaN(pid)) {
|
|
212
|
+
try {
|
|
213
|
+
process.kill(pid, 'SIGTERM');
|
|
214
|
+
console.log(`Stopped DockerNet Agent (PID ${pid})`);
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
console.log(`PID ${pid} is not valid or process is not running`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
await fs.remove(pidFile);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
console.log(`No PID file found (${pidFile}). Agent may not be running.`);
|
|
224
|
+
}
|
|
225
|
+
process.exit(0);
|
|
226
|
+
}
|
|
227
|
+
async handleRestart() {
|
|
228
|
+
await this.handleStop();
|
|
229
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
230
|
+
await this.runDaemon();
|
|
231
|
+
process.exit(0);
|
|
232
|
+
}
|
|
233
|
+
printUsage() {
|
|
234
|
+
console.log(`
|
|
235
|
+
DockerNet Agent CLI
|
|
236
|
+
|
|
237
|
+
Usage:
|
|
238
|
+
agent --apiKey <API_KEY> : Save/update API key in config
|
|
239
|
+
agent --config : Show current config (mask API key)
|
|
240
|
+
agent --profiles : List saved profiles on this machine
|
|
241
|
+
agent --upgrade : Download latest agent script
|
|
242
|
+
agent --log : Show log (if running as daemon)
|
|
243
|
+
agent --version : Show agent version
|
|
244
|
+
agent --run : Run agent as daemon
|
|
245
|
+
agent --stop : Stop running daemon
|
|
246
|
+
agent --restart : Restart agent daemon
|
|
247
|
+
|
|
248
|
+
Run without arguments to see version.
|
|
249
|
+
`);
|
|
250
|
+
process.exit(0);
|
|
251
|
+
}
|
|
252
|
+
async runDaemon() {
|
|
253
|
+
if (this.isRunning) {
|
|
254
|
+
this.logger.warn('Agent is already running');
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
this.isRunning = true;
|
|
258
|
+
this.logger.log('Starting DockerNet Agent daemon...');
|
|
259
|
+
try {
|
|
260
|
+
await this.dockerService.checkDependencies();
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
this.logger.error(`Dependency check failed: ${error.message}`);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
const config = await this.configService.loadConfig();
|
|
267
|
+
if (!config.apiKey) {
|
|
268
|
+
this.logger.error('API key not found. Run: agent --apiKey YOUR_API_KEY');
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
271
|
+
await this.apiService.setApiKey(config.apiKey);
|
|
272
|
+
if (!config.machineKey) {
|
|
273
|
+
const machineKey = this.machineService.generateMachineKey();
|
|
274
|
+
await this.configService.saveConfig({
|
|
275
|
+
apiKey: config.apiKey,
|
|
276
|
+
machineKey,
|
|
277
|
+
serverUrl: config.serverUrl,
|
|
278
|
+
});
|
|
279
|
+
this.logger.log(`Generated new machine key: ${machineKey}`);
|
|
280
|
+
}
|
|
281
|
+
await this.machineService.registerMachine();
|
|
282
|
+
this.logger.log('Checking and updating saved profiles status...');
|
|
283
|
+
try {
|
|
284
|
+
await this.profileService.updateAllProfilesStatus();
|
|
285
|
+
this.logger.log('Initial profile status check completed');
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
this.logger.error(`Error during initial profile status check: ${error.message}`);
|
|
289
|
+
}
|
|
290
|
+
await this.logService.autoStreamLogsForAllContainers();
|
|
291
|
+
await this.eventService.startPolling();
|
|
292
|
+
const statusInterval = setInterval(async () => {
|
|
293
|
+
await this.machineService.updateMachineStatus('live');
|
|
294
|
+
}, 5000);
|
|
295
|
+
const logInterval = setInterval(async () => {
|
|
296
|
+
await this.logService.autoStreamLogsForAllContainers();
|
|
297
|
+
}, 10000);
|
|
298
|
+
process.on('SIGTERM', async () => {
|
|
299
|
+
this.logger.log('Received SIGTERM, shutting down...');
|
|
300
|
+
clearInterval(statusInterval);
|
|
301
|
+
clearInterval(logInterval);
|
|
302
|
+
this.eventService.stopPolling();
|
|
303
|
+
this.websocketClientService.disconnect();
|
|
304
|
+
await this.machineService.updateMachineStatus('exit');
|
|
305
|
+
process.exit(0);
|
|
306
|
+
});
|
|
307
|
+
process.on('SIGINT', async () => {
|
|
308
|
+
this.logger.log('Received SIGINT, shutting down...');
|
|
309
|
+
clearInterval(statusInterval);
|
|
310
|
+
clearInterval(logInterval);
|
|
311
|
+
this.eventService.stopPolling();
|
|
312
|
+
this.websocketClientService.disconnect();
|
|
313
|
+
await this.machineService.updateMachineStatus('exit');
|
|
314
|
+
process.exit(0);
|
|
315
|
+
});
|
|
316
|
+
this.logger.log('DockerNet Agent daemon is running...');
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
exports.AgentCommand = AgentCommand;
|
|
320
|
+
__decorate([
|
|
321
|
+
(0, nest_commander_1.Option)({
|
|
322
|
+
flags: '--apiKey <apiKey>',
|
|
323
|
+
description: 'Save/update API key in config',
|
|
324
|
+
}),
|
|
325
|
+
__metadata("design:type", Function),
|
|
326
|
+
__metadata("design:paramtypes", [String]),
|
|
327
|
+
__metadata("design:returntype", String)
|
|
328
|
+
], AgentCommand.prototype, "parseApiKey", null);
|
|
329
|
+
__decorate([
|
|
330
|
+
(0, nest_commander_1.Option)({
|
|
331
|
+
flags: '--config',
|
|
332
|
+
description: 'Show current config (mask API key)',
|
|
333
|
+
}),
|
|
334
|
+
__metadata("design:type", Function),
|
|
335
|
+
__metadata("design:paramtypes", []),
|
|
336
|
+
__metadata("design:returntype", Boolean)
|
|
337
|
+
], AgentCommand.prototype, "parseConfig", null);
|
|
338
|
+
__decorate([
|
|
339
|
+
(0, nest_commander_1.Option)({
|
|
340
|
+
flags: '--profiles',
|
|
341
|
+
description: 'List saved profiles on this machine',
|
|
342
|
+
}),
|
|
343
|
+
__metadata("design:type", Function),
|
|
344
|
+
__metadata("design:paramtypes", []),
|
|
345
|
+
__metadata("design:returntype", Boolean)
|
|
346
|
+
], AgentCommand.prototype, "parseProfiles", null);
|
|
347
|
+
__decorate([
|
|
348
|
+
(0, nest_commander_1.Option)({
|
|
349
|
+
flags: '--upgrade',
|
|
350
|
+
description: 'Download latest agent script',
|
|
351
|
+
}),
|
|
352
|
+
__metadata("design:type", Function),
|
|
353
|
+
__metadata("design:paramtypes", []),
|
|
354
|
+
__metadata("design:returntype", Boolean)
|
|
355
|
+
], AgentCommand.prototype, "parseUpgrade", null);
|
|
356
|
+
__decorate([
|
|
357
|
+
(0, nest_commander_1.Option)({
|
|
358
|
+
flags: '--log',
|
|
359
|
+
description: 'Show log (if running as daemon)',
|
|
360
|
+
}),
|
|
361
|
+
__metadata("design:type", Function),
|
|
362
|
+
__metadata("design:paramtypes", []),
|
|
363
|
+
__metadata("design:returntype", Boolean)
|
|
364
|
+
], AgentCommand.prototype, "parseLog", null);
|
|
365
|
+
__decorate([
|
|
366
|
+
(0, nest_commander_1.Option)({
|
|
367
|
+
flags: '--version',
|
|
368
|
+
description: 'Show agent version',
|
|
369
|
+
}),
|
|
370
|
+
__metadata("design:type", Function),
|
|
371
|
+
__metadata("design:paramtypes", []),
|
|
372
|
+
__metadata("design:returntype", Boolean)
|
|
373
|
+
], AgentCommand.prototype, "parseVersion", null);
|
|
374
|
+
__decorate([
|
|
375
|
+
(0, nest_commander_1.Option)({
|
|
376
|
+
flags: '--run',
|
|
377
|
+
description: 'Run agent as daemon',
|
|
378
|
+
}),
|
|
379
|
+
__metadata("design:type", Function),
|
|
380
|
+
__metadata("design:paramtypes", []),
|
|
381
|
+
__metadata("design:returntype", Boolean)
|
|
382
|
+
], AgentCommand.prototype, "parseRun", null);
|
|
383
|
+
__decorate([
|
|
384
|
+
(0, nest_commander_1.Option)({
|
|
385
|
+
flags: '--stop',
|
|
386
|
+
description: 'Stop running daemon',
|
|
387
|
+
}),
|
|
388
|
+
__metadata("design:type", Function),
|
|
389
|
+
__metadata("design:paramtypes", []),
|
|
390
|
+
__metadata("design:returntype", Boolean)
|
|
391
|
+
], AgentCommand.prototype, "parseStop", null);
|
|
392
|
+
__decorate([
|
|
393
|
+
(0, nest_commander_1.Option)({
|
|
394
|
+
flags: '--restart',
|
|
395
|
+
description: 'Restart agent daemon',
|
|
396
|
+
}),
|
|
397
|
+
__metadata("design:type", Function),
|
|
398
|
+
__metadata("design:paramtypes", []),
|
|
399
|
+
__metadata("design:returntype", Boolean)
|
|
400
|
+
], AgentCommand.prototype, "parseRestart", null);
|
|
401
|
+
exports.AgentCommand = AgentCommand = AgentCommand_1 = __decorate([
|
|
402
|
+
(0, common_1.Injectable)(),
|
|
403
|
+
(0, nest_commander_1.Command)({
|
|
404
|
+
name: 'agent',
|
|
405
|
+
description: 'DockerNet Agent CLI',
|
|
406
|
+
}),
|
|
407
|
+
__metadata("design:paramtypes", [api_service_1.ApiService,
|
|
408
|
+
config_service_1.ConfigService,
|
|
409
|
+
docker_service_1.DockerService,
|
|
410
|
+
event_service_1.EventService,
|
|
411
|
+
log_service_1.LogService,
|
|
412
|
+
machine_service_1.MachineService,
|
|
413
|
+
profile_service_1.ProfileService,
|
|
414
|
+
volume_sync_service_1.VolumeSyncService,
|
|
415
|
+
websocket_client_service_1.WebSocketClientService])
|
|
416
|
+
], AgentCommand);
|
|
417
|
+
//# sourceMappingURL=agent.command.js.map
|