@docker-digital/dockernet-agent 0.1.3 → 0.1.6

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 (188) hide show
  1. package/dist/{agent → apps/agent/src/agent}/agent.module.js +21 -4
  2. package/dist/apps/agent/src/agent/agent.module.js.map +1 -0
  3. package/dist/{agent → apps/agent/src/agent}/commands/agent.command.d.ts +3 -3
  4. package/dist/{agent → apps/agent/src/agent}/commands/agent.command.js +2 -3
  5. package/dist/apps/agent/src/agent/commands/agent.command.js.map +1 -0
  6. package/dist/{agent → apps/agent/src/agent}/commands/apikey.command.d.ts +3 -3
  7. package/dist/{agent → apps/agent/src/agent}/commands/apikey.command.js +2 -3
  8. package/dist/apps/agent/src/agent/commands/apikey.command.js.map +1 -0
  9. package/dist/apps/agent/src/agent/commands/config.command.d.ts +7 -0
  10. package/dist/{agent → apps/agent/src/agent}/commands/config.command.js +2 -3
  11. package/dist/apps/agent/src/agent/commands/config.command.js.map +1 -0
  12. package/dist/apps/agent/src/agent/commands/log.command.d.ts +7 -0
  13. package/dist/{agent → apps/agent/src/agent}/commands/log.command.js +2 -3
  14. package/dist/apps/agent/src/agent/commands/log.command.js.map +1 -0
  15. package/dist/apps/agent/src/agent/commands/profiles.command.d.ts +7 -0
  16. package/dist/{agent → apps/agent/src/agent}/commands/profiles.command.js +2 -3
  17. package/dist/apps/agent/src/agent/commands/profiles.command.js.map +1 -0
  18. package/dist/{agent → apps/agent/src/agent}/commands/restart.command.d.ts +1 -1
  19. package/dist/{agent → apps/agent/src/agent}/commands/restart.command.js +1 -2
  20. package/dist/apps/agent/src/agent/commands/restart.command.js.map +1 -0
  21. package/dist/{agent → apps/agent/src/agent}/commands/run.command.d.ts +14 -7
  22. package/dist/apps/agent/src/agent/commands/run.command.js +534 -0
  23. package/dist/apps/agent/src/agent/commands/run.command.js.map +1 -0
  24. package/dist/apps/agent/src/agent/commands/service.command.d.ts +14 -0
  25. package/dist/apps/agent/src/agent/commands/service.command.js +132 -0
  26. package/dist/apps/agent/src/agent/commands/service.command.js.map +1 -0
  27. package/dist/apps/agent/src/agent/commands/stop.command.d.ts +7 -0
  28. package/dist/{agent → apps/agent/src/agent}/commands/stop.command.js +2 -3
  29. package/dist/apps/agent/src/agent/commands/stop.command.js.map +1 -0
  30. package/dist/apps/agent/src/agent/commands/upgrade.command.d.ts +7 -0
  31. package/dist/{agent → apps/agent/src/agent}/commands/upgrade.command.js +2 -3
  32. package/dist/apps/agent/src/agent/commands/upgrade.command.js.map +1 -0
  33. package/dist/{agent → apps/agent/src/agent}/commands/version.command.d.ts +1 -1
  34. package/dist/{agent → apps/agent/src/agent}/commands/version.command.js +1 -1
  35. package/dist/apps/agent/src/agent/commands/version.command.js.map +1 -0
  36. package/dist/{agent → apps/agent/src/agent}/services/api.service.d.ts +4 -2
  37. package/dist/{agent → apps/agent/src/agent}/services/api.service.js +124 -24
  38. package/dist/apps/agent/src/agent/services/api.service.js.map +1 -0
  39. package/dist/{agent → apps/agent/src/agent}/services/config.service.d.ts +4 -3
  40. package/dist/{agent → apps/agent/src/agent}/services/config.service.js +11 -8
  41. package/dist/apps/agent/src/agent/services/config.service.js.map +1 -0
  42. package/dist/{agent → apps/agent/src/agent}/services/docker-event.service.js +17 -2
  43. package/dist/apps/agent/src/agent/services/docker-event.service.js.map +1 -0
  44. package/dist/{agent → apps/agent/src/agent}/services/docker.service.d.ts +6 -2
  45. package/dist/{agent → apps/agent/src/agent}/services/docker.service.js +122 -7
  46. package/dist/apps/agent/src/agent/services/docker.service.js.map +1 -0
  47. package/dist/{agent → apps/agent/src/agent}/services/event-websocket-client.service.d.ts +14 -2
  48. package/dist/apps/agent/src/agent/services/event-websocket-client.service.js +680 -0
  49. package/dist/apps/agent/src/agent/services/event-websocket-client.service.js.map +1 -0
  50. package/dist/{agent → apps/agent/src/agent}/services/event.service.d.ts +3 -2
  51. package/dist/apps/agent/src/agent/services/event.service.js +500 -0
  52. package/dist/apps/agent/src/agent/services/event.service.js.map +1 -0
  53. package/dist/apps/agent/src/agent/services/index.d.ts +14 -0
  54. package/dist/apps/agent/src/agent/services/index.js +31 -0
  55. package/dist/apps/agent/src/agent/services/index.js.map +1 -0
  56. package/dist/{agent → apps/agent/src/agent}/services/log.service.d.ts +11 -4
  57. package/dist/{agent → apps/agent/src/agent}/services/log.service.js +41 -11
  58. package/dist/apps/agent/src/agent/services/log.service.js.map +1 -0
  59. package/dist/{agent → apps/agent/src/agent}/services/machine.service.d.ts +2 -2
  60. package/dist/apps/agent/src/agent/services/machine.service.js +356 -0
  61. package/dist/apps/agent/src/agent/services/machine.service.js.map +1 -0
  62. package/dist/{agent → apps/agent/src/agent}/services/nebula.service.d.ts +2 -2
  63. package/dist/{agent → apps/agent/src/agent}/services/nebula.service.js +144 -21
  64. package/dist/apps/agent/src/agent/services/nebula.service.js.map +1 -0
  65. package/dist/{agent → apps/agent/src/agent}/services/profile.service.d.ts +11 -2
  66. package/dist/apps/agent/src/agent/services/profile.service.js +1300 -0
  67. package/dist/apps/agent/src/agent/services/profile.service.js.map +1 -0
  68. package/dist/{agent → apps/agent/src/agent}/services/terminal.service.d.ts +2 -2
  69. package/dist/{agent → apps/agent/src/agent}/services/terminal.service.js +107 -12
  70. package/dist/apps/agent/src/agent/services/terminal.service.js.map +1 -0
  71. package/dist/{agent → apps/agent/src/agent}/services/volume-backup.service.d.ts +2 -2
  72. package/dist/{agent → apps/agent/src/agent}/services/volume-backup.service.js +27 -4
  73. package/dist/apps/agent/src/agent/services/volume-backup.service.js.map +1 -0
  74. package/dist/{agent → apps/agent/src/agent}/services/volume-sync.service.d.ts +2 -2
  75. package/dist/{agent → apps/agent/src/agent}/services/volume-sync.service.js +19 -1
  76. package/dist/apps/agent/src/agent/services/volume-sync.service.js.map +1 -0
  77. package/dist/{agent → apps/agent/src/agent}/services/websocket-client.service.d.ts +11 -3
  78. package/dist/{agent → apps/agent/src/agent}/services/websocket-client.service.js +33 -12
  79. package/dist/apps/agent/src/agent/services/websocket-client.service.js.map +1 -0
  80. package/dist/apps/agent/src/api/agent-control.controller.d.ts +43 -0
  81. package/dist/apps/agent/src/api/agent-control.controller.js +123 -0
  82. package/dist/apps/agent/src/api/agent-control.controller.js.map +1 -0
  83. package/dist/apps/agent/src/api/api.module.d.ts +2 -0
  84. package/dist/apps/agent/src/api/api.module.js +62 -0
  85. package/dist/apps/agent/src/api/api.module.js.map +1 -0
  86. package/dist/apps/agent/src/api/health.controller.d.ts +9 -0
  87. package/dist/apps/agent/src/api/health.controller.js +36 -0
  88. package/dist/apps/agent/src/api/health.controller.js.map +1 -0
  89. package/dist/apps/agent/src/api/logs.controller.d.ts +11 -0
  90. package/dist/apps/agent/src/api/logs.controller.js +50 -0
  91. package/dist/apps/agent/src/api/logs.controller.js.map +1 -0
  92. package/dist/apps/agent/src/api/machine.controller.d.ts +21 -0
  93. package/dist/apps/agent/src/api/machine.controller.js +48 -0
  94. package/dist/apps/agent/src/api/machine.controller.js.map +1 -0
  95. package/dist/apps/agent/src/api/metrics.controller.d.ts +17 -0
  96. package/dist/apps/agent/src/api/metrics.controller.js +48 -0
  97. package/dist/apps/agent/src/api/metrics.controller.js.map +1 -0
  98. package/dist/apps/agent/src/api/network.controller.d.ts +15 -0
  99. package/dist/apps/agent/src/api/network.controller.js +50 -0
  100. package/dist/apps/agent/src/api/network.controller.js.map +1 -0
  101. package/dist/apps/agent/src/api/profiles.controller.d.ts +16 -0
  102. package/dist/apps/agent/src/api/profiles.controller.js +71 -0
  103. package/dist/apps/agent/src/api/profiles.controller.js.map +1 -0
  104. package/dist/apps/agent/src/api/services.controller.d.ts +10 -0
  105. package/dist/apps/agent/src/api/services.controller.js +77 -0
  106. package/dist/apps/agent/src/api/services.controller.js.map +1 -0
  107. package/dist/apps/agent/src/api/status.controller.d.ts +53 -0
  108. package/dist/apps/agent/src/api/status.controller.js +157 -0
  109. package/dist/apps/agent/src/api/status.controller.js.map +1 -0
  110. package/dist/{app.module.js → apps/agent/src/app.module.js} +4 -0
  111. package/dist/apps/agent/src/app.module.js.map +1 -0
  112. package/dist/apps/agent/src/common/logging/correlation-id.middleware.d.ts +15 -0
  113. package/dist/apps/agent/src/common/logging/correlation-id.middleware.js +36 -0
  114. package/dist/apps/agent/src/common/logging/correlation-id.middleware.js.map +1 -0
  115. package/dist/apps/agent/src/common/logging/correlation-id.storage.d.ts +9 -0
  116. package/dist/apps/agent/src/common/logging/correlation-id.storage.js +35 -0
  117. package/dist/apps/agent/src/common/logging/correlation-id.storage.js.map +1 -0
  118. package/dist/apps/agent/src/common/logging/index.d.ts +4 -0
  119. package/dist/apps/agent/src/common/logging/index.js +12 -0
  120. package/dist/apps/agent/src/common/logging/index.js.map +1 -0
  121. package/dist/apps/agent/src/common/logging/logging.module.d.ts +4 -0
  122. package/dist/apps/agent/src/common/logging/logging.module.js +27 -0
  123. package/dist/apps/agent/src/common/logging/logging.module.js.map +1 -0
  124. package/dist/apps/agent/src/common/logging/structured-logger.service.d.ts +28 -0
  125. package/dist/apps/agent/src/common/logging/structured-logger.service.js +96 -0
  126. package/dist/apps/agent/src/common/logging/structured-logger.service.js.map +1 -0
  127. package/dist/apps/agent/src/index.js.map +1 -0
  128. package/dist/apps/agent/src/main.js +14 -0
  129. package/dist/apps/agent/src/main.js.map +1 -0
  130. package/dist/shared/common/utils/cli-logger.util.d.ts +59 -0
  131. package/dist/shared/common/utils/cli-logger.util.js +233 -0
  132. package/dist/shared/common/utils/cli-logger.util.js.map +1 -0
  133. package/dist/shared/common/utils/constant.d.ts +22 -0
  134. package/dist/shared/common/utils/constant.js +26 -0
  135. package/dist/shared/common/utils/constant.js.map +1 -0
  136. package/dist/shared/common/utils/index.d.ts +3 -0
  137. package/dist/shared/common/utils/index.js +20 -0
  138. package/dist/shared/common/utils/index.js.map +1 -0
  139. package/dist/shared/common/utils/request.util.d.ts +2 -0
  140. package/dist/shared/common/utils/request.util.js +36 -0
  141. package/dist/shared/common/utils/request.util.js.map +1 -0
  142. package/dist/tsconfig.tsbuildinfo +1 -1
  143. package/package.json +24 -6
  144. package/dist/agent/agent.module.js.map +0 -1
  145. package/dist/agent/commands/agent.command.js.map +0 -1
  146. package/dist/agent/commands/apikey.command.js.map +0 -1
  147. package/dist/agent/commands/config.command.d.ts +0 -7
  148. package/dist/agent/commands/config.command.js.map +0 -1
  149. package/dist/agent/commands/log.command.d.ts +0 -7
  150. package/dist/agent/commands/log.command.js.map +0 -1
  151. package/dist/agent/commands/profiles.command.d.ts +0 -7
  152. package/dist/agent/commands/profiles.command.js.map +0 -1
  153. package/dist/agent/commands/restart.command.js.map +0 -1
  154. package/dist/agent/commands/run.command.js +0 -252
  155. package/dist/agent/commands/run.command.js.map +0 -1
  156. package/dist/agent/commands/stop.command.d.ts +0 -7
  157. package/dist/agent/commands/stop.command.js.map +0 -1
  158. package/dist/agent/commands/upgrade.command.d.ts +0 -7
  159. package/dist/agent/commands/upgrade.command.js.map +0 -1
  160. package/dist/agent/commands/version.command.js.map +0 -1
  161. package/dist/agent/services/api.service.js.map +0 -1
  162. package/dist/agent/services/config.service.js.map +0 -1
  163. package/dist/agent/services/docker-event.service.js.map +0 -1
  164. package/dist/agent/services/docker.service.js.map +0 -1
  165. package/dist/agent/services/event-websocket-client.service.js +0 -248
  166. package/dist/agent/services/event-websocket-client.service.js.map +0 -1
  167. package/dist/agent/services/event.service.js +0 -255
  168. package/dist/agent/services/event.service.js.map +0 -1
  169. package/dist/agent/services/log.service.js.map +0 -1
  170. package/dist/agent/services/machine.service.js +0 -195
  171. package/dist/agent/services/machine.service.js.map +0 -1
  172. package/dist/agent/services/nebula.service.js.map +0 -1
  173. package/dist/agent/services/profile.service.js +0 -541
  174. package/dist/agent/services/profile.service.js.map +0 -1
  175. package/dist/agent/services/terminal.service.js.map +0 -1
  176. package/dist/agent/services/volume-backup.service.js.map +0 -1
  177. package/dist/agent/services/volume-sync.service.js.map +0 -1
  178. package/dist/agent/services/websocket-client.service.js.map +0 -1
  179. package/dist/app.module.js.map +0 -1
  180. package/dist/index.js.map +0 -1
  181. package/dist/main.js +0 -51
  182. package/dist/main.js.map +0 -1
  183. /package/dist/{agent → apps/agent/src/agent}/agent.module.d.ts +0 -0
  184. /package/dist/{agent → apps/agent/src/agent}/services/docker-event.service.d.ts +0 -0
  185. /package/dist/{app.module.d.ts → apps/agent/src/app.module.d.ts} +0 -0
  186. /package/dist/{index.d.ts → apps/agent/src/index.d.ts} +0 -0
  187. /package/dist/{index.js → apps/agent/src/index.js} +0 -0
  188. /package/dist/{main.d.ts → apps/agent/src/main.d.ts} +0 -0
@@ -0,0 +1,1300 @@
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 ProfileService_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ProfileService = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const fs = require("fs-extra");
16
+ const path = require("path");
17
+ const child_process_1 = require("child_process");
18
+ const util_1 = require("util");
19
+ const api_service_1 = require("./api.service");
20
+ const config_service_1 = require("./config.service");
21
+ const docker_service_1 = require("./docker.service");
22
+ const docker_event_service_1 = require("./docker-event.service");
23
+ const log_service_1 = require("./log.service");
24
+ const websocket_client_service_1 = require("./websocket-client.service");
25
+ const utils_1 = require("../../../../../shared/common/utils");
26
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
27
+ function wrapDockerCommand(cmd) {
28
+ const originalUser = process.env.SUDO_USER;
29
+ if (originalUser) {
30
+ const escapedCmd = cmd.replace(/'/g, "'\\''");
31
+ return `sudo -u ${originalUser} sh -c '${escapedCmd}'`;
32
+ }
33
+ return cmd;
34
+ }
35
+ let ProfileService = ProfileService_1 = class ProfileService {
36
+ constructor(apiService, configService, dockerService, dockerEventService, logService, websocketClientService) {
37
+ this.apiService = apiService;
38
+ this.configService = configService;
39
+ this.dockerService = dockerService;
40
+ this.dockerEventService = dockerEventService;
41
+ this.logService = logService;
42
+ this.websocketClientService = websocketClientService;
43
+ this.logger = new common_1.Logger(ProfileService_1.name);
44
+ this.useEventDrivenUpdates = false;
45
+ }
46
+ async onModuleInit() {
47
+ this.dockerEventService.onContainerStateChangedCallback((event) => this.handleContainerStateChanged(event));
48
+ }
49
+ async initializeWebSocket() {
50
+ try {
51
+ await this.websocketClientService.connect();
52
+ if (this.websocketClientService.isWebSocketConnected()) {
53
+ this.useEventDrivenUpdates = true;
54
+ utils_1.cliLogger.block({
55
+ title: 'Event-driven status updates enabled (WebSocket connected)',
56
+ context: 'ProfileService',
57
+ func: 'initializeWebSocket',
58
+ type: 'info',
59
+ metadata: {},
60
+ });
61
+ }
62
+ else {
63
+ utils_1.cliLogger.block({
64
+ title: 'WebSocket not available, falling back to polling',
65
+ context: 'ProfileService',
66
+ func: 'initializeWebSocket',
67
+ type: 'warning',
68
+ metadata: {},
69
+ });
70
+ }
71
+ }
72
+ catch (error) {
73
+ this.logger.warn(`Failed to connect WebSocket: ${error.message}, using polling fallback`);
74
+ }
75
+ }
76
+ async getProfileDetails(profileId) {
77
+ let endpoint = `/docker-profiles/${profileId}`;
78
+ this.logger.debug(`Calling API: GET ${endpoint}`);
79
+ const maxRetries = 24;
80
+ const response = (await this.apiService.callApi('GET', endpoint, undefined, maxRetries, 5000));
81
+ utils_1.cliLogger.block({
82
+ title: 'API response received',
83
+ context: 'ProfileService',
84
+ func: 'getProfileDetails',
85
+ type: 'debug',
86
+ metadata: {
87
+ response: response ? 'success' : 'null',
88
+ },
89
+ });
90
+ if (!response) {
91
+ utils_1.cliLogger.block({
92
+ title: 'No response from API for profile',
93
+ context: 'ProfileService',
94
+ func: 'getProfileDetails',
95
+ type: 'warning',
96
+ metadata: {
97
+ profileId: profileId,
98
+ },
99
+ });
100
+ return null;
101
+ }
102
+ const responseData = response.data || response;
103
+ if (!responseData) {
104
+ utils_1.cliLogger.block({
105
+ title: 'No data in API response for profile',
106
+ context: 'ProfileService',
107
+ func: 'getProfileDetails',
108
+ type: 'warning',
109
+ metadata: {
110
+ profileId: profileId,
111
+ },
112
+ });
113
+ return null;
114
+ }
115
+ if (responseData.profile) {
116
+ const profile = responseData.profile;
117
+ if (responseData.docker_compose_content) {
118
+ profile.docker_compose_content = responseData.docker_compose_content;
119
+ profile.dockerComposeContent = responseData.docker_compose_content;
120
+ }
121
+ if (responseData.services) {
122
+ profile.services_status = responseData.services;
123
+ profile.servicesStatus = responseData.services;
124
+ }
125
+ utils_1.cliLogger.block({
126
+ title: 'Profile parsed with docker_compose_content',
127
+ context: 'ProfileService',
128
+ func: 'getProfileDetails',
129
+ type: 'debug',
130
+ metadata: {
131
+ profile: profile ? 'success' : 'null',
132
+ },
133
+ });
134
+ return profile;
135
+ }
136
+ utils_1.cliLogger.block({
137
+ title: 'Profile parsed',
138
+ context: 'ProfileService',
139
+ func: 'getProfileDetails',
140
+ type: 'debug',
141
+ metadata: {
142
+ responseData: responseData ? 'success' : 'null',
143
+ },
144
+ });
145
+ return responseData;
146
+ }
147
+ async getProfilesByMachineKey() {
148
+ const machineKey = await this.configService.getMachineKey();
149
+ if (!machineKey) {
150
+ utils_1.cliLogger.block({
151
+ title: 'Machine key not found, cannot fetch profiles',
152
+ context: 'ProfileService',
153
+ func: 'getProfilesByMachineKey',
154
+ type: 'warning',
155
+ metadata: {},
156
+ });
157
+ return [];
158
+ }
159
+ try {
160
+ const endpoint = `/docker-profiles?machine_key=${machineKey}`;
161
+ const profilesResponse = await this.apiService.callApi('GET', endpoint, undefined, 3, 5000);
162
+ if (!profilesResponse) {
163
+ return [];
164
+ }
165
+ const profiles = profilesResponse.rows || [];
166
+ utils_1.cliLogger.block({
167
+ title: `Fetched ${profiles.length} profile(s) for machine`,
168
+ context: 'ProfileService',
169
+ func: 'getProfilesByMachineKey',
170
+ type: 'info',
171
+ metadata: { machineKey, profileCount: profiles.length },
172
+ });
173
+ return profiles;
174
+ }
175
+ catch (error) {
176
+ utils_1.cliLogger.block({
177
+ title: `Error fetching profiles: ${error.message}`,
178
+ context: 'ProfileService',
179
+ func: 'getProfilesByMachineKey',
180
+ type: 'error',
181
+ metadata: { error: error.message },
182
+ });
183
+ return [];
184
+ }
185
+ }
186
+ async startProfile(eventKey, profileId, workspaceId) {
187
+ utils_1.cliLogger.startProcess(`Starting profile: ${profileId}`, '🚀');
188
+ if (!profileId) {
189
+ utils_1.cliLogger.error('Profile ID is required');
190
+ return;
191
+ }
192
+ if (!workspaceId || workspaceId === 'null' || workspaceId === 'undefined') {
193
+ utils_1.cliLogger.error('Workspace ID is required');
194
+ }
195
+ this.logger.log(`Starting profile: ${profileId}, workspace: ${workspaceId}`);
196
+ this.logger.log(`[DEBUG] After Starting profile log, about to fetch profile details`);
197
+ utils_1.cliLogger.step(1, 5, 'Fetching profile details...');
198
+ this.logger.log(`[DEBUG] Calling getProfileDetails for ${profileId}`);
199
+ const profile = await this.getProfileDetails(profileId);
200
+ utils_1.cliLogger.block({
201
+ title: 'getProfileDetails returned',
202
+ context: 'ProfileService',
203
+ func: 'startProfile',
204
+ type: 'debug',
205
+ metadata: {
206
+ profile: profile ? 'success' : 'null',
207
+ },
208
+ });
209
+ if (!profile) {
210
+ utils_1.cliLogger.error('Cannot get profile details from server');
211
+ utils_1.cliLogger.block({
212
+ title: 'Cannot get profile details from server',
213
+ context: 'ProfileService',
214
+ func: 'startProfile',
215
+ type: 'error',
216
+ metadata: {
217
+ profileId: profileId,
218
+ },
219
+ });
220
+ await this.websocketClientService.sendStatusUpdate({
221
+ type: 'profile_update',
222
+ workspace_id: workspaceId,
223
+ profile_key: profileId,
224
+ status: 'failed',
225
+ error: 'Cannot get profile details from server',
226
+ timestamp: Date.now(),
227
+ });
228
+ return;
229
+ }
230
+ utils_1.cliLogger.block({
231
+ title: 'Profile details retrieved successfully',
232
+ context: 'ProfileService',
233
+ func: 'startProfile',
234
+ type: 'debug',
235
+ metadata: {
236
+ profileId: profileId,
237
+ },
238
+ });
239
+ const machineKey = await this.configService.getMachineKey();
240
+ const profileMachineKey = profile.machine_key;
241
+ if (profileMachineKey && profileMachineKey !== machineKey) {
242
+ utils_1.cliLogger.block({
243
+ title: 'Skipping profile - machine_key mismatch',
244
+ context: 'ProfileService',
245
+ func: 'startProfile',
246
+ type: 'warning',
247
+ metadata: {
248
+ profileId: profileId,
249
+ profileMachineKey: profileMachineKey,
250
+ machineKey: machineKey,
251
+ },
252
+ });
253
+ return;
254
+ }
255
+ const deployPath = profile.deploy_path ||
256
+ profile.deployPath ||
257
+ '/opt/docker-compose';
258
+ utils_1.cliLogger.block({
259
+ title: 'Using deploy_path',
260
+ context: 'ProfileService',
261
+ func: 'startProfile',
262
+ type: 'debug',
263
+ metadata: {
264
+ deployPath: deployPath,
265
+ },
266
+ });
267
+ utils_1.cliLogger.step(2, 5, 'Creating profile directory and files...');
268
+ this.logger.log(`[DEBUG] Creating deploy_path directory: ${deployPath}`);
269
+ await fs.ensureDir(deployPath);
270
+ const profileDir = path.join(this.configService.workDirPath, profileId);
271
+ await fs.ensureDir(profileDir);
272
+ utils_1.cliLogger.block({
273
+ title: 'Profile directory created',
274
+ context: 'ProfileService',
275
+ func: 'startProfile',
276
+ type: 'debug',
277
+ metadata: {
278
+ profileDir: profileDir,
279
+ },
280
+ });
281
+ const envContent = profile.env_content || profile.envContent || '';
282
+ const envFile = path.join(deployPath, `.env_${profileId}`);
283
+ utils_1.cliLogger.block({
284
+ title: 'Env content length',
285
+ context: 'ProfileService',
286
+ func: 'startProfile',
287
+ type: 'debug',
288
+ metadata: {
289
+ envContentLength: envContent?.length || 0,
290
+ },
291
+ });
292
+ utils_1.cliLogger.block({
293
+ title: 'Profile keys',
294
+ context: 'ProfileService',
295
+ func: 'startProfile',
296
+ type: 'debug',
297
+ metadata: {
298
+ profileKeys: Object.keys(profile).join(', '),
299
+ },
300
+ });
301
+ await fs.writeFile(envFile, envContent || '');
302
+ utils_1.cliLogger.block({
303
+ title: 'Created .env file in deployPath',
304
+ context: 'ProfileService',
305
+ func: 'startProfile',
306
+ type: 'debug',
307
+ metadata: {
308
+ envFile: envFile,
309
+ deployPath: deployPath,
310
+ hasContent: !!envContent && envContent.length > 0,
311
+ contentLength: envContent?.length || 0,
312
+ },
313
+ });
314
+ if (!envContent || envContent.length === 0) {
315
+ utils_1.cliLogger.block({
316
+ title: '.env file created but empty (no env_content in profile)',
317
+ context: 'ProfileService',
318
+ func: 'startProfile',
319
+ type: 'info',
320
+ metadata: {
321
+ profileId: profileId,
322
+ },
323
+ });
324
+ }
325
+ const dockerComposeContent = profile.docker_compose_content ||
326
+ profile.dockerComposeContent ||
327
+ profile.data?.docker_compose_content ||
328
+ profile.data?.dockerComposeContent;
329
+ if (!dockerComposeContent) {
330
+ utils_1.cliLogger.error('Profile does not have docker-compose content');
331
+ await this.websocketClientService.sendStatusUpdate({
332
+ type: 'profile_update',
333
+ workspace_id: workspaceId,
334
+ profile_key: profileId,
335
+ status: 'failed',
336
+ error: 'Profile does not have docker-compose content',
337
+ timestamp: Date.now(),
338
+ });
339
+ return;
340
+ }
341
+ await this.handlePrivateRegistries(profile);
342
+ const composeFile = path.join(deployPath, `docker-compose_${profileId}.yaml`);
343
+ await fs.writeFile(composeFile, dockerComposeContent);
344
+ utils_1.cliLogger.success('Files created successfully');
345
+ utils_1.cliLogger.block({
346
+ title: 'Created docker-compose file',
347
+ context: 'ProfileService',
348
+ func: 'startProfile',
349
+ type: 'debug',
350
+ metadata: {
351
+ composeFile: composeFile,
352
+ },
353
+ });
354
+ utils_1.cliLogger.step(3, 5, 'Starting Docker containers...');
355
+ utils_1.cliLogger.block({
356
+ title: 'Executing docker-compose up',
357
+ context: 'ProfileService',
358
+ func: 'startProfile',
359
+ type: 'debug',
360
+ metadata: {
361
+ profileId: profileId,
362
+ },
363
+ });
364
+ try {
365
+ await this.handlePrivateRegistries(profile);
366
+ const envFile = path.join(deployPath, `.env_${profileId}`);
367
+ let composeCommand = `docker-compose -p "${profileId}" -f "${composeFile}"`;
368
+ if (fs.existsSync(envFile)) {
369
+ composeCommand += ` --env-file "${envFile}"`;
370
+ utils_1.cliLogger.block({
371
+ title: 'Using .env file',
372
+ context: 'ProfileService',
373
+ func: 'startProfile',
374
+ type: 'debug',
375
+ metadata: {
376
+ envFile: envFile,
377
+ deployPath: deployPath,
378
+ hasContent: !!envContent && envContent.length > 0,
379
+ },
380
+ });
381
+ }
382
+ else {
383
+ utils_1.cliLogger.block({
384
+ title: '.env file not found (unexpected)',
385
+ context: 'ProfileService',
386
+ func: 'startProfile',
387
+ type: 'warning',
388
+ metadata: {
389
+ profileId: profileId,
390
+ envFile: envFile,
391
+ },
392
+ });
393
+ }
394
+ composeCommand += ` up -d`;
395
+ const finalCommand = wrapDockerCommand(composeCommand);
396
+ utils_1.cliLogger.block({
397
+ title: 'Docker compose command',
398
+ context: 'ProfileService',
399
+ func: 'startProfile',
400
+ type: 'debug',
401
+ metadata: {
402
+ command: finalCommand,
403
+ },
404
+ });
405
+ const { stdout, stderr } = await execAsync(finalCommand, {
406
+ cwd: deployPath,
407
+ });
408
+ utils_1.cliLogger.block({
409
+ title: 'Docker compose up stdout',
410
+ context: 'ProfileService',
411
+ func: 'startProfile',
412
+ type: 'debug',
413
+ metadata: {
414
+ stdout: stdout,
415
+ },
416
+ });
417
+ if (stderr && !stderr.includes('Creating')) {
418
+ utils_1.cliLogger.block({
419
+ title: 'Docker compose warnings',
420
+ context: 'ProfileService',
421
+ func: 'startProfile',
422
+ type: 'warning',
423
+ metadata: {
424
+ stderr: stderr,
425
+ },
426
+ });
427
+ }
428
+ utils_1.cliLogger.block({
429
+ title: 'Docker compose up completed successfully',
430
+ context: 'ProfileService',
431
+ func: 'startProfile',
432
+ type: 'success',
433
+ metadata: {
434
+ profileId: profileId,
435
+ },
436
+ });
437
+ utils_1.cliLogger.success('Docker containers started');
438
+ }
439
+ catch (error) {
440
+ utils_1.cliLogger.error(`Docker compose up failed: ${error.message}`);
441
+ utils_1.cliLogger.block({
442
+ title: 'Docker compose up failed',
443
+ context: 'ProfileService',
444
+ func: 'startProfile',
445
+ type: 'error',
446
+ metadata: {
447
+ profileId: profileId,
448
+ error: error.message,
449
+ },
450
+ });
451
+ utils_1.cliLogger.block({
452
+ title: 'Error details',
453
+ context: 'ProfileService',
454
+ func: 'startProfile',
455
+ type: 'error',
456
+ metadata: {
457
+ error: error,
458
+ },
459
+ });
460
+ try {
461
+ if (fs.existsSync(composeFile)) {
462
+ await fs.remove(composeFile);
463
+ utils_1.cliLogger.block({
464
+ title: 'Removed docker-compose file',
465
+ context: 'ProfileService',
466
+ func: 'startProfile',
467
+ type: 'debug',
468
+ metadata: {
469
+ composeFile: composeFile,
470
+ },
471
+ });
472
+ }
473
+ const envFile = path.join(deployPath, `.env_${profileId}`);
474
+ if (fs.existsSync(envFile)) {
475
+ await fs.remove(envFile);
476
+ utils_1.cliLogger.block({
477
+ title: 'Removed .env file',
478
+ context: 'ProfileService',
479
+ func: 'startProfile',
480
+ type: 'debug',
481
+ metadata: {
482
+ envFile: envFile,
483
+ deployPath: deployPath,
484
+ },
485
+ });
486
+ }
487
+ const files = await fs.readdir(profileDir);
488
+ if (files.length === 0) {
489
+ await fs.remove(profileDir);
490
+ utils_1.cliLogger.block({
491
+ title: 'Removed empty profile directory',
492
+ context: 'ProfileService',
493
+ func: 'startProfile',
494
+ type: 'debug',
495
+ metadata: {
496
+ profileDir: profileDir,
497
+ },
498
+ });
499
+ }
500
+ utils_1.cliLogger.block({
501
+ title: 'Cleanup completed',
502
+ context: 'ProfileService',
503
+ func: 'startProfile',
504
+ type: 'success',
505
+ metadata: {
506
+ profileId: profileId,
507
+ },
508
+ });
509
+ }
510
+ catch (cleanupError) {
511
+ utils_1.cliLogger.block({
512
+ title: 'Cleanup failed',
513
+ context: 'ProfileService',
514
+ func: 'startProfile',
515
+ type: 'error',
516
+ metadata: {
517
+ error: cleanupError.message,
518
+ },
519
+ });
520
+ }
521
+ await this.websocketClientService.sendStatusUpdate({
522
+ type: 'profile_update',
523
+ workspace_id: workspaceId,
524
+ profile_key: profileId,
525
+ status: 'failed',
526
+ error: `docker compose up failed: ${error.message}`,
527
+ timestamp: Date.now(),
528
+ });
529
+ return;
530
+ }
531
+ utils_1.cliLogger.step(4, 5, 'Starting log streaming...');
532
+ await this.logService.startLogStreamsForProfile(profileId);
533
+ utils_1.cliLogger.block({
534
+ title: 'Log streaming started',
535
+ context: 'ProfileService',
536
+ func: 'startProfile',
537
+ type: 'success',
538
+ metadata: {
539
+ profileId: profileId,
540
+ },
541
+ });
542
+ utils_1.cliLogger.step(5, 5, 'Saving profile metadata...');
543
+ const metadataFile = path.join(profileDir, '.profile_metadata');
544
+ await fs.writeFile(metadataFile, `workspace_id=${workspaceId}\nprofile_id=${profileId}\n`);
545
+ utils_1.cliLogger.block({
546
+ title: 'Metadata saved',
547
+ context: 'ProfileService',
548
+ func: 'startProfile',
549
+ type: 'success',
550
+ metadata: {
551
+ profileId: profileId,
552
+ },
553
+ });
554
+ await this.updateProfileStatus(profileId, workspaceId, true);
555
+ await this.websocketClientService.sendStatusUpdate({
556
+ type: 'profile_update',
557
+ workspace_id: workspaceId,
558
+ profile_key: profileId,
559
+ status: 'active',
560
+ timestamp: Date.now(),
561
+ });
562
+ utils_1.cliLogger.completeProcess(`Profile ${profileId} started successfully!`, {
563
+ 'Profile ID': profileId,
564
+ 'Workspace ID': workspaceId,
565
+ 'Deploy Path': deployPath,
566
+ 'Compose File': composeFile,
567
+ });
568
+ utils_1.cliLogger.block({
569
+ title: 'Profile started successfully',
570
+ context: 'ProfileService',
571
+ func: 'startProfile',
572
+ type: 'success',
573
+ metadata: {
574
+ profileId: profileId,
575
+ },
576
+ });
577
+ }
578
+ async stopProfile(eventKey, profileId, workspaceId) {
579
+ utils_1.cliLogger.block({
580
+ title: 'Stopping profile',
581
+ context: 'ProfileService',
582
+ func: 'stopProfile',
583
+ type: 'info',
584
+ metadata: {
585
+ profileId: profileId,
586
+ workspaceId: workspaceId || null
587
+ },
588
+ });
589
+ if (!profileId) {
590
+ utils_1.cliLogger.block({
591
+ title: 'Profile ID is required',
592
+ context: 'ProfileService',
593
+ func: 'stopProfile',
594
+ type: 'error',
595
+ metadata: {
596
+ profileId: profileId,
597
+ workspaceId: workspaceId || null
598
+ },
599
+ });
600
+ return;
601
+ }
602
+ this.logger.log(`Stopping profile: ${profileId}`);
603
+ let deployPath = '/opt/docker-compose';
604
+ if (workspaceId && workspaceId !== 'null' && workspaceId !== 'undefined') {
605
+ const profile = await this.getProfileDetails(profileId);
606
+ if (profile) {
607
+ deployPath =
608
+ profile.deploy_path ||
609
+ profile.deployPath ||
610
+ '/opt/docker-compose';
611
+ const machineKey = await this.configService.getMachineKey();
612
+ const profileMachineKey = profile.machine_key;
613
+ if (profileMachineKey && profileMachineKey !== machineKey) {
614
+ utils_1.cliLogger.block({
615
+ title: 'Skipping profile - machine_key mismatch',
616
+ context: 'ProfileService',
617
+ func: 'stopProfile',
618
+ type: 'warning',
619
+ metadata: {
620
+ profileId: profileId,
621
+ },
622
+ });
623
+ }
624
+ }
625
+ }
626
+ else {
627
+ const profile = await this.getProfileDetails(profileId);
628
+ if (profile) {
629
+ deployPath =
630
+ profile.deploy_path ||
631
+ profile.deployPath ||
632
+ '/opt/docker-compose';
633
+ }
634
+ }
635
+ utils_1.cliLogger.block({
636
+ title: 'Using deploy_path for stop',
637
+ context: 'ProfileService',
638
+ func: 'stopProfile',
639
+ type: 'debug',
640
+ metadata: {
641
+ deployPath: deployPath,
642
+ },
643
+ });
644
+ const composeFile = path.join(deployPath, `docker-compose_${profileId}.yaml`);
645
+ if (!fs.existsSync(composeFile)) {
646
+ utils_1.cliLogger.block({
647
+ title: 'Docker-compose file not found',
648
+ context: 'ProfileService',
649
+ func: 'stopProfile',
650
+ type: 'error',
651
+ metadata: {
652
+ profileId: profileId,
653
+ },
654
+ });
655
+ return;
656
+ }
657
+ utils_1.cliLogger.step(1, 2, 'Stopping log streams...');
658
+ await this.logService.stopLogStreamsForProfile(profileId);
659
+ utils_1.cliLogger.success('Log streams stopped');
660
+ utils_1.cliLogger.step(2, 2, 'Stopping Docker containers (docker-compose stop)...');
661
+ try {
662
+ const stopCommand = wrapDockerCommand(`docker-compose -p "${profileId}" -f "${composeFile}" stop`);
663
+ await execAsync(stopCommand, {
664
+ cwd: deployPath,
665
+ });
666
+ utils_1.cliLogger.success('Docker containers stopped (stopped state, not removed)');
667
+ }
668
+ catch (error) {
669
+ utils_1.cliLogger.error(`docker compose stop failed: ${error.message}`);
670
+ await this.markEventFailed(eventKey, `docker compose stop failed: ${error.message}`);
671
+ return;
672
+ }
673
+ if (workspaceId && workspaceId !== 'null' && workspaceId !== 'undefined') {
674
+ await this.updateProfileStatus(profileId, workspaceId, false);
675
+ }
676
+ utils_1.cliLogger.block({
677
+ title: 'Profile stopped successfully',
678
+ context: 'ProfileService',
679
+ func: 'stopProfile',
680
+ type: 'success',
681
+ metadata: {
682
+ profileId: profileId,
683
+ },
684
+ });
685
+ }
686
+ async restartService(eventKey, profileId, workspaceId, serviceName) {
687
+ utils_1.cliLogger.block({
688
+ title: 'Restarting service',
689
+ context: 'ProfileService',
690
+ func: 'restartService',
691
+ type: 'info',
692
+ metadata: {
693
+ profileId: profileId,
694
+ serviceName: serviceName,
695
+ },
696
+ });
697
+ const profile = await this.getProfileDetails(profileId);
698
+ const deployPath = profile?.deploy_path ||
699
+ profile?.deployPath ||
700
+ '/opt/docker-compose';
701
+ utils_1.cliLogger.block({
702
+ title: 'Using deploy_path for restart',
703
+ context: 'ProfileService',
704
+ func: 'restartService',
705
+ type: 'debug',
706
+ metadata: {
707
+ deployPath: deployPath,
708
+ },
709
+ });
710
+ const composeFile = path.join(deployPath, `docker-compose_${profileId}.yaml`);
711
+ if (!fs.existsSync(composeFile)) {
712
+ utils_1.cliLogger.block({
713
+ title: 'Docker-compose file not found',
714
+ context: 'ProfileService',
715
+ func: 'restartService',
716
+ type: 'error',
717
+ metadata: {
718
+ profileId: profileId,
719
+ serviceName: serviceName,
720
+ composeFile: composeFile,
721
+ },
722
+ });
723
+ return;
724
+ }
725
+ try {
726
+ utils_1.cliLogger.step(1, 1, `Restarting service ${serviceName}...`);
727
+ const restartCommand = wrapDockerCommand(`docker-compose -p "${profileId}" -f "${composeFile}" restart ${serviceName}`);
728
+ await execAsync(restartCommand, {
729
+ cwd: deployPath,
730
+ });
731
+ utils_1.cliLogger.success(`Service ${serviceName} restarted successfully`);
732
+ utils_1.cliLogger.completeProcess(`Service ${serviceName} restarted successfully!`, {
733
+ Service: serviceName,
734
+ Profile: profileId,
735
+ });
736
+ this.logger.log(`Service ${serviceName} restarted successfully`);
737
+ }
738
+ catch (error) {
739
+ utils_1.cliLogger.error(`docker compose restart failed: ${error.message}`);
740
+ await this.markEventFailed(eventKey, `docker compose restart failed: ${error.message}`);
741
+ }
742
+ }
743
+ async downProfile(eventKey, profileId, workspaceId) {
744
+ utils_1.cliLogger.block({
745
+ title: 'Down profile (docker-compose down)',
746
+ context: 'ProfileService',
747
+ func: 'downProfile',
748
+ type: 'info',
749
+ metadata: {
750
+ profileId: profileId,
751
+ workspaceId: workspaceId || null,
752
+ },
753
+ });
754
+ if (!profileId) {
755
+ utils_1.cliLogger.block({
756
+ title: 'Profile ID is required',
757
+ context: 'ProfileService',
758
+ func: 'downProfile',
759
+ type: 'error',
760
+ metadata: {
761
+ profileId: profileId,
762
+ workspaceId: workspaceId || null,
763
+ },
764
+ });
765
+ return;
766
+ }
767
+ let deployPath = '/opt/docker-compose';
768
+ const profile = await this.getProfileDetails(profileId);
769
+ if (profile) {
770
+ deployPath =
771
+ profile.deploy_path || profile.deployPath || '/opt/docker-compose';
772
+ }
773
+ const composeFile = path.join(deployPath, `docker-compose_${profileId}.yaml`);
774
+ if (!fs.existsSync(composeFile)) {
775
+ utils_1.cliLogger.block({
776
+ title: 'Docker-compose file not found (downProfile)',
777
+ context: 'ProfileService',
778
+ func: 'downProfile',
779
+ type: 'error',
780
+ metadata: {
781
+ profileId: profileId,
782
+ composeFile: composeFile,
783
+ },
784
+ });
785
+ return;
786
+ }
787
+ utils_1.cliLogger.step(1, 2, 'Stopping log streams (downProfile)...');
788
+ await this.logService.stopLogStreamsForProfile(profileId);
789
+ utils_1.cliLogger.step(2, 2, 'Running docker-compose down...');
790
+ try {
791
+ const downCommand = wrapDockerCommand(`docker-compose -p "${profileId}" -f "${composeFile}" down`);
792
+ await execAsync(downCommand, {
793
+ cwd: deployPath,
794
+ });
795
+ utils_1.cliLogger.success('Docker-compose down completed');
796
+ }
797
+ catch (error) {
798
+ utils_1.cliLogger.error(`docker compose down failed: ${error.message}`);
799
+ await this.markEventFailed(eventKey, `docker compose down failed: ${error.message}`);
800
+ return;
801
+ }
802
+ const profileDir = path.join(this.configService.workDirPath, profileId);
803
+ const metadataFile = path.join(profileDir, '.profile_metadata');
804
+ await fs.remove(metadataFile).catch(() => { });
805
+ if (workspaceId && workspaceId !== 'null' && workspaceId !== 'undefined') {
806
+ await this.updateProfileStatus(profileId, workspaceId, false);
807
+ }
808
+ utils_1.cliLogger.block({
809
+ title: 'Profile down completed',
810
+ context: 'ProfileService',
811
+ func: 'downProfile',
812
+ type: 'success',
813
+ metadata: {
814
+ profileId: profileId,
815
+ },
816
+ });
817
+ }
818
+ async updateProfileStatus(profileId, workspaceId, isActive) {
819
+ const payload = {
820
+ workspace_id: workspaceId,
821
+ is_active: isActive,
822
+ };
823
+ await this.apiService.callApi('PUT', `/docker-profiles/${profileId}/status`, payload, -1, 10000);
824
+ }
825
+ async updateProfileServicesStatus(profileId, workspaceId) {
826
+ const servicesResponse = await this.apiService.callApi('GET', `/docker-profiles/${profileId}/services?workspace_id=${workspaceId}`, undefined, -1, 5000);
827
+ if (!servicesResponse) {
828
+ this.logger.error('[ERROR updateProfileServicesStatus] No services response from API');
829
+ return;
830
+ }
831
+ const services = servicesResponse.data?.rows || servicesResponse.rows || [];
832
+ if (!services || services.length === 0) {
833
+ this.logger.error('[ERROR updateProfileServicesStatus] No services found for profile');
834
+ return;
835
+ }
836
+ const profileDir = path.join(this.configService.workDirPath, profileId);
837
+ const servicesStatus = [];
838
+ for (const service of services) {
839
+ const serviceKey = service.key;
840
+ const serviceName = service.name;
841
+ if (!serviceKey || !serviceName) {
842
+ this.logger.error('[ERROR updateProfileServicesStatus] No service key or name found for service');
843
+ continue;
844
+ }
845
+ const status = await this.dockerService.getServiceStatus(serviceName, profileDir, profileId);
846
+ if (status && status !== 'unknown') {
847
+ servicesStatus.push({
848
+ service_key: serviceKey,
849
+ service_name: serviceName,
850
+ status,
851
+ });
852
+ }
853
+ }
854
+ if (servicesStatus.length > 0) {
855
+ const payload = {
856
+ profile_key: profileId,
857
+ workspace_id: workspaceId,
858
+ services: servicesStatus,
859
+ };
860
+ await this.apiService.callApi('PUT', `/docker-profiles/${profileId}/services/status`, payload, -1, 5000);
861
+ const hasRunning = servicesStatus.some((s) => /^(running|up)/i.test(s.status));
862
+ await this.updateProfileStatus(profileId, workspaceId, hasRunning);
863
+ }
864
+ else {
865
+ const composeFile = path.join(profileDir, `docker-compose_${profileId}.yaml`);
866
+ if (fs.existsSync(composeFile)) {
867
+ const containers = await this.dockerService.getProfileContainers(profileId);
868
+ const runningContainers = containers.filter((c) => c.State === 'running' || (c.Status && /^Up/i.test(c.Status)));
869
+ const hasRunning = runningContainers.length > 0;
870
+ await this.updateProfileStatus(profileId, workspaceId, hasRunning);
871
+ }
872
+ else {
873
+ await this.updateProfileStatus(profileId, workspaceId, false);
874
+ }
875
+ }
876
+ }
877
+ async handlePrivateRegistries(profile) {
878
+ const services = profile.services || [];
879
+ const registries = new Map();
880
+ utils_1.cliLogger.block({
881
+ title: 'Detect private registries',
882
+ context: 'ProfileService',
883
+ func: 'handlePrivateRegistries',
884
+ type: 'debug',
885
+ metadata: {
886
+ servicesCount: Array.isArray(services) ? services.length : 0,
887
+ },
888
+ });
889
+ const sampleServices = Array.isArray(services) ? services.slice(0, 3) : [];
890
+ for (const s of sampleServices) {
891
+ const rawConfig = s?.config || {};
892
+ const cfg = rawConfig?.config || rawConfig;
893
+ utils_1.cliLogger.block({
894
+ title: 'Service config sample',
895
+ context: 'ProfileService',
896
+ func: 'handlePrivateRegistries',
897
+ type: 'debug',
898
+ metadata: {
899
+ serviceName: s?.name,
900
+ hasConfig: !!s?.config,
901
+ rawConfigKeys: rawConfig ? Object.keys(rawConfig).slice(0, 20) : [],
902
+ configKeys: cfg ? Object.keys(cfg).slice(0, 30) : [],
903
+ isPrivate: cfg?.is_private_registry || cfg?.isPrivateRegistry,
904
+ hasRegistryUrl: !!(cfg?.registry_url || cfg?.registryUrl),
905
+ hasRegistryUsername: !!(cfg?.registry_username || cfg?.registryUsername),
906
+ hasRegistryPassword: !!(cfg?.registry_password || cfg?.registryPassword),
907
+ },
908
+ });
909
+ }
910
+ for (const service of services) {
911
+ const rawConfig = service.config || {};
912
+ const config = rawConfig.config || rawConfig;
913
+ const isPrivate = config.is_private_registry || config.isPrivateRegistry;
914
+ utils_1.cliLogger.block({
915
+ title: 'Checking service for private registry',
916
+ context: 'ProfileService',
917
+ func: 'handlePrivateRegistries',
918
+ type: 'debug',
919
+ metadata: {
920
+ serviceName: service?.name,
921
+ hasConfig: !!service.config,
922
+ isPrivate,
923
+ registryUrl: config.registry_url || config.registryUrl,
924
+ hasUsername: !!(config.registry_username || config.registryUsername),
925
+ hasPassword: !!(config.registry_password || config.registryPassword),
926
+ },
927
+ });
928
+ if (isPrivate) {
929
+ const url = config.registry_url || config.registryUrl;
930
+ const username = config.registry_username || config.registryUsername;
931
+ const password = config.registry_password || config.registryPassword;
932
+ if (url && username && password) {
933
+ if (!registries.has(url)) {
934
+ registries.set(url, { url, username, password });
935
+ }
936
+ }
937
+ else {
938
+ utils_1.cliLogger.block({
939
+ title: 'Skip private registry (missing credentials)',
940
+ context: 'ProfileService',
941
+ func: 'handlePrivateRegistries',
942
+ type: 'warning',
943
+ metadata: {
944
+ serviceName: service?.name,
945
+ hasUrl: !!url,
946
+ hasUsername: !!username,
947
+ hasPassword: !!password,
948
+ },
949
+ });
950
+ }
951
+ }
952
+ }
953
+ utils_1.cliLogger.block({
954
+ title: 'Private registries detected',
955
+ context: 'ProfileService',
956
+ func: 'handlePrivateRegistries',
957
+ type: 'debug',
958
+ metadata: {
959
+ registriesCount: registries.size,
960
+ registries: Array.from(registries.keys()),
961
+ },
962
+ });
963
+ if (registries.size > 0) {
964
+ utils_1.cliLogger.step(2, 5, `Logging into ${registries.size} private registry(ies)...`);
965
+ }
966
+ for (const registry of registries.values()) {
967
+ const success = await this.dockerService.dockerLogin(registry.url, registry.username, registry.password);
968
+ if (success) {
969
+ this.logger.log(`Docker login successful for registry: ${registry.url}`);
970
+ utils_1.cliLogger.success(`Docker login successful for registry: ${registry.url}`);
971
+ }
972
+ else {
973
+ const errorMsg = `Docker login failed for registry: ${registry.url}. Please check credentials.`;
974
+ this.logger.error(errorMsg);
975
+ utils_1.cliLogger.error(errorMsg);
976
+ }
977
+ }
978
+ }
979
+ async markEventRunning(eventKey) {
980
+ await this.apiService.callApi('PUT', `/events/${eventKey}`, {
981
+ status: 'running',
982
+ }, -1, 5000);
983
+ }
984
+ async markEventExecuted(eventKey) {
985
+ await this.apiService.callApi('PUT', `/events/${eventKey}`, {
986
+ status: 'executed',
987
+ is_executed: true,
988
+ }, -1, 5000);
989
+ }
990
+ async markEventFailed(eventKey, error) {
991
+ await this.apiService.callApi('PUT', `/events/${eventKey}`, {
992
+ status: 'failed',
993
+ is_executed: true,
994
+ error,
995
+ }, -1, 5000);
996
+ }
997
+ async handleContainerStateChanged(event) {
998
+ if (!this.useEventDrivenUpdates) {
999
+ utils_1.cliLogger.block({
1000
+ title: 'Event-driven updates disabled, skipping Docker event',
1001
+ context: 'ProfileService',
1002
+ func: 'handleContainerStateChanged',
1003
+ type: 'warning',
1004
+ metadata: {
1005
+ event: event,
1006
+ },
1007
+ });
1008
+ return;
1009
+ }
1010
+ utils_1.cliLogger.block({
1011
+ title: 'Container state changed',
1012
+ context: 'ProfileService',
1013
+ func: 'handleContainerStateChanged',
1014
+ type: 'info',
1015
+ metadata: {
1016
+ event: event,
1017
+ },
1018
+ });
1019
+ const workspaceId = await this.getWorkspaceId(event.profileId);
1020
+ if (!workspaceId) {
1021
+ utils_1.cliLogger.block({
1022
+ title: 'No workspace_id found for profile',
1023
+ context: 'ProfileService',
1024
+ func: 'handleContainerStateChanged',
1025
+ type: 'warning',
1026
+ metadata: {
1027
+ profileId: event.profileId,
1028
+ },
1029
+ });
1030
+ }
1031
+ const profileDir = path.join(this.configService.workDirPath, event.profileId);
1032
+ const status = await this.dockerService.getServiceStatus(event.serviceName, profileDir, event.profileId);
1033
+ utils_1.cliLogger.block({
1034
+ title: 'Send Profile Status Update',
1035
+ context: 'ProfileService',
1036
+ func: 'handleContainerStateChanged',
1037
+ type: 'info',
1038
+ metadata: {
1039
+ workspaceId: workspaceId,
1040
+ profileId: event.profileId,
1041
+ serviceName: event.serviceName,
1042
+ },
1043
+ });
1044
+ await this.websocketClientService.sendStatusUpdate({
1045
+ type: 'service_status',
1046
+ workspace_id: workspaceId,
1047
+ profile_key: event.profileId,
1048
+ service_key: event.serviceName,
1049
+ service_name: event.serviceName,
1050
+ status: status,
1051
+ container_id: event.containerId,
1052
+ timestamp: Date.now(),
1053
+ });
1054
+ await this.updateProfileStatusFromDocker(event.profileId, workspaceId);
1055
+ }
1056
+ async getWorkspaceId(profileId) {
1057
+ const profileDir = path.join(this.configService.workDirPath, profileId);
1058
+ const metadataFile = path.join(profileDir, '.profile_metadata');
1059
+ if (!fs.existsSync(metadataFile)) {
1060
+ return null;
1061
+ }
1062
+ try {
1063
+ const metadata = await fs.readFile(metadataFile, 'utf-8');
1064
+ const workspaceIdMatch = metadata.match(/^workspace_id=(.+)$/m);
1065
+ const workspaceId = workspaceIdMatch?.[1]?.trim();
1066
+ if (!workspaceId ||
1067
+ workspaceId === 'null' ||
1068
+ workspaceId === 'undefined') {
1069
+ return null;
1070
+ }
1071
+ return workspaceId;
1072
+ }
1073
+ catch (error) {
1074
+ this.logger.error(`Error reading metadata for ${profileId}: ${error.message}`);
1075
+ return null;
1076
+ }
1077
+ }
1078
+ async updateProfileStatusFromDocker(profileId, workspaceId) {
1079
+ const profileDir = path.join(this.configService.workDirPath, profileId);
1080
+ const containers = await this.dockerService.getProfileContainers(profileId);
1081
+ const runningContainers = containers.filter((c) => c.State === 'running' || (c.Status && /^Up/i.test(c.Status)));
1082
+ const hasRunning = runningContainers.length > 0;
1083
+ await this.websocketClientService.sendStatusUpdate({
1084
+ type: 'profile_status',
1085
+ workspace_id: workspaceId,
1086
+ profile_key: profileId,
1087
+ is_active: hasRunning,
1088
+ timestamp: Date.now(),
1089
+ });
1090
+ }
1091
+ async updateAllProfilesStatus() {
1092
+ const machineKey = await this.configService.getMachineKey();
1093
+ if (!machineKey) {
1094
+ utils_1.cliLogger.block({
1095
+ title: 'Machine key not found, cannot update profiles status',
1096
+ context: 'ProfileService',
1097
+ func: 'updateAllProfilesStatus',
1098
+ type: 'warning',
1099
+ metadata: {},
1100
+ });
1101
+ return;
1102
+ }
1103
+ utils_1.cliLogger.block({
1104
+ title: `Starting updateAllProfilesStatus for machine_key: ${machineKey}`,
1105
+ context: 'ProfileService',
1106
+ func: 'updateAllProfilesStatus',
1107
+ type: 'info',
1108
+ metadata: {
1109
+ machineKey: machineKey,
1110
+ },
1111
+ });
1112
+ try {
1113
+ const endpoint = `/docker-profiles?machine_key=${machineKey}`;
1114
+ utils_1.cliLogger.block({
1115
+ title: `Calling API: GET ${endpoint} (full URL will be: ${this.configService.apiBaseUrl}${endpoint})`,
1116
+ context: 'ProfileService',
1117
+ func: 'updateAllProfilesStatus',
1118
+ type: 'debug',
1119
+ metadata: {
1120
+ endpoint: endpoint,
1121
+ },
1122
+ });
1123
+ const profilesResponse = await this.apiService.callApi('GET', endpoint, undefined, -1, 5000);
1124
+ if (!profilesResponse) {
1125
+ utils_1.cliLogger.block({
1126
+ title: `No profiles response from API for machine_key: ${machineKey}`,
1127
+ context: 'ProfileService',
1128
+ func: 'updateAllProfilesStatus',
1129
+ type: 'warning',
1130
+ metadata: {
1131
+ machineKey: machineKey,
1132
+ },
1133
+ });
1134
+ return;
1135
+ }
1136
+ utils_1.cliLogger.block({
1137
+ title: `API response received: ${JSON.stringify(profilesResponse).substring(0, 500)}`,
1138
+ context: 'ProfileService',
1139
+ func: 'updateAllProfilesStatus',
1140
+ type: 'debug',
1141
+ metadata: {},
1142
+ });
1143
+ utils_1.cliLogger.debug(`API response structure: ${JSON.stringify({
1144
+ hasData: !!profilesResponse.data,
1145
+ hasRows: !!profilesResponse.rows,
1146
+ dataKeys: profilesResponse.data
1147
+ ? Object.keys(profilesResponse.data)
1148
+ : [],
1149
+ responseKeys: Object.keys(profilesResponse),
1150
+ isArray: Array.isArray(profilesResponse),
1151
+ })}`);
1152
+ let profiles = profilesResponse.rows || [];
1153
+ if (!profiles || profiles.length === 0) {
1154
+ utils_1.cliLogger.block({
1155
+ title: `No profiles found for machine_key: ${machineKey}`,
1156
+ context: 'ProfileService',
1157
+ func: 'updateAllProfilesStatus',
1158
+ type: 'warning',
1159
+ metadata: {
1160
+ machineKey: machineKey,
1161
+ },
1162
+ });
1163
+ return;
1164
+ }
1165
+ utils_1.cliLogger.block({
1166
+ title: `Found ${profiles.length} profile(s) for machine_key: ${machineKey}`,
1167
+ context: 'ProfileService',
1168
+ func: 'updateAllProfilesStatus',
1169
+ type: 'debug',
1170
+ metadata: {
1171
+ machineKey: machineKey,
1172
+ profiles: profiles.map((p) => p.key),
1173
+ },
1174
+ });
1175
+ let updatedCount = 0;
1176
+ for (const profile of profiles) {
1177
+ try {
1178
+ const profileId = profile.key || profile.profile_key;
1179
+ const workspaceId = profile.workspace_id;
1180
+ const services = profile.services || [];
1181
+ if (!profileId || !workspaceId) {
1182
+ utils_1.cliLogger.block({
1183
+ title: 'Skipping profile - missing profileId or workspaceId',
1184
+ context: 'ProfileService',
1185
+ func: 'updateAllProfilesStatus',
1186
+ type: 'warning',
1187
+ metadata: {
1188
+ profileId: profileId,
1189
+ workspaceId: workspaceId,
1190
+ },
1191
+ });
1192
+ continue;
1193
+ }
1194
+ if (!services || services.length === 0) {
1195
+ utils_1.cliLogger.block({
1196
+ title: `Profile ${profileId} has no services, checking profile status only`,
1197
+ context: 'ProfileService',
1198
+ func: 'updateAllProfilesStatus',
1199
+ type: 'debug',
1200
+ metadata: {
1201
+ profileId: profileId,
1202
+ },
1203
+ });
1204
+ const containers = await this.dockerService.getProfileContainers(profileId);
1205
+ const runningContainers = containers.filter((c) => c.State === 'running' || (c.Status && /^Up/i.test(c.Status)));
1206
+ const hasRunning = runningContainers.length > 0;
1207
+ await this.updateProfileStatus(profileId, workspaceId, hasRunning);
1208
+ updatedCount++;
1209
+ continue;
1210
+ }
1211
+ const servicesStatus = [];
1212
+ for (const service of services) {
1213
+ const serviceKey = service.key;
1214
+ const serviceName = service.name;
1215
+ if (!serviceKey || !serviceName) {
1216
+ continue;
1217
+ }
1218
+ const containerNamePatterns = [
1219
+ `${serviceKey}_${serviceName}`,
1220
+ `${serviceKey}-${serviceName}`,
1221
+ `${serviceKey}${serviceName}`,
1222
+ ];
1223
+ let status = null;
1224
+ for (const containerName of containerNamePatterns) {
1225
+ status =
1226
+ await this.dockerService.getContainerStatus(containerName);
1227
+ if (status) {
1228
+ break;
1229
+ }
1230
+ }
1231
+ if (!status) {
1232
+ const profileDir = path.join(this.configService.workDirPath, profileId);
1233
+ status = await this.dockerService.getServiceStatus(serviceName, profileDir, profileId);
1234
+ }
1235
+ if (status && status !== 'unknown') {
1236
+ servicesStatus.push({
1237
+ service_key: serviceKey,
1238
+ service_name: serviceName,
1239
+ status,
1240
+ });
1241
+ }
1242
+ }
1243
+ if (servicesStatus.length > 0) {
1244
+ const payload = {
1245
+ profile_key: profileId,
1246
+ workspace_id: workspaceId,
1247
+ services: servicesStatus,
1248
+ };
1249
+ await this.apiService.callApi('PUT', `/docker-profiles/${profileId}/services/status`, payload, -1, 5000);
1250
+ const hasRunning = servicesStatus.some((s) => /^(running|up)/i.test(s.status));
1251
+ await this.updateProfileStatus(profileId, workspaceId, hasRunning);
1252
+ }
1253
+ else {
1254
+ const containers = await this.dockerService.getProfileContainers(profileId);
1255
+ const runningContainers = containers.filter((c) => c.State === 'running' || (c.Status && /^Up/i.test(c.Status)));
1256
+ const hasRunning = runningContainers.length > 0;
1257
+ await this.updateProfileStatus(profileId, workspaceId, hasRunning);
1258
+ }
1259
+ updatedCount++;
1260
+ }
1261
+ catch (error) {
1262
+ this.logger.error(`Error updating profile ${profile?.key || 'unknown'}: ${error.message}`);
1263
+ }
1264
+ }
1265
+ if (updatedCount > 0) {
1266
+ utils_1.cliLogger.block({
1267
+ title: `Updated status for ${updatedCount} profile(s)`,
1268
+ context: 'ProfileService',
1269
+ func: 'updateAllProfilesStatus',
1270
+ type: 'debug',
1271
+ metadata: {
1272
+ updatedCount: updatedCount,
1273
+ },
1274
+ });
1275
+ }
1276
+ }
1277
+ catch (error) {
1278
+ utils_1.cliLogger.block({
1279
+ title: `Error in updateAllProfilesStatus: ${error.message}`,
1280
+ context: 'ProfileService',
1281
+ func: 'updateAllProfilesStatus',
1282
+ type: 'error',
1283
+ metadata: {
1284
+ error: error.message,
1285
+ },
1286
+ });
1287
+ }
1288
+ }
1289
+ };
1290
+ exports.ProfileService = ProfileService;
1291
+ exports.ProfileService = ProfileService = ProfileService_1 = __decorate([
1292
+ (0, common_1.Injectable)(),
1293
+ __metadata("design:paramtypes", [api_service_1.ApiService,
1294
+ config_service_1.ConfigAgentService,
1295
+ docker_service_1.DockerService,
1296
+ docker_event_service_1.DockerEventService,
1297
+ log_service_1.LogService,
1298
+ websocket_client_service_1.WebSocketClientService])
1299
+ ], ProfileService);
1300
+ //# sourceMappingURL=profile.service.js.map