buildhive-agent 1.0.0-beta.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/README.md +166 -0
- package/dist/__tests__/fakes/FakeDockerManager.d.ts +115 -0
- package/dist/__tests__/fakes/FakeDockerManager.d.ts.map +1 -0
- package/dist/__tests__/fakes/FakeDockerManager.js +203 -0
- package/dist/__tests__/fakes/FakeDockerManager.js.map +1 -0
- package/dist/acceptanceChecker.d.ts +26 -0
- package/dist/acceptanceChecker.d.ts.map +1 -0
- package/dist/acceptanceChecker.js +64 -0
- package/dist/acceptanceChecker.js.map +1 -0
- package/dist/advancedAgent.d.ts +161 -0
- package/dist/advancedAgent.d.ts.map +1 -0
- package/dist/advancedAgent.js +604 -0
- package/dist/advancedAgent.js.map +1 -0
- package/dist/agent.d.ts +101 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +490 -0
- package/dist/agent.js.map +1 -0
- package/dist/api/jobStatusApi.d.ts +88 -0
- package/dist/api/jobStatusApi.d.ts.map +1 -0
- package/dist/api/jobStatusApi.js +240 -0
- package/dist/api/jobStatusApi.js.map +1 -0
- package/dist/autoUpdater.d.ts +135 -0
- package/dist/autoUpdater.d.ts.map +1 -0
- package/dist/autoUpdater.js +494 -0
- package/dist/autoUpdater.js.map +1 -0
- package/dist/cacheManager.d.ts +108 -0
- package/dist/cacheManager.d.ts.map +1 -0
- package/dist/cacheManager.js +300 -0
- package/dist/cacheManager.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +749 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +30 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +35 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +45 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +269 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +193 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +90 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validation.d.ts +28 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +397 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/docker.d.ts +96 -0
- package/dist/docker.d.ts.map +1 -0
- package/dist/docker.js +411 -0
- package/dist/docker.js.map +1 -0
- package/dist/enhancedJobExecutor.d.ts +81 -0
- package/dist/enhancedJobExecutor.d.ts.map +1 -0
- package/dist/enhancedJobExecutor.js +223 -0
- package/dist/enhancedJobExecutor.js.map +1 -0
- package/dist/executors/executorFactory.d.ts +46 -0
- package/dist/executors/executorFactory.d.ts.map +1 -0
- package/dist/executors/executorFactory.js +80 -0
- package/dist/executors/executorFactory.js.map +1 -0
- package/dist/executors/index.d.ts +7 -0
- package/dist/executors/index.d.ts.map +1 -0
- package/dist/executors/index.js +6 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/nativeExecutor.d.ts +60 -0
- package/dist/executors/nativeExecutor.d.ts.map +1 -0
- package/dist/executors/nativeExecutor.js +311 -0
- package/dist/executors/nativeExecutor.js.map +1 -0
- package/dist/executors/types.d.ts +38 -0
- package/dist/executors/types.d.ts.map +1 -0
- package/dist/executors/types.js +9 -0
- package/dist/executors/types.js.map +1 -0
- package/dist/healthMonitor.d.ts +213 -0
- package/dist/healthMonitor.d.ts.map +1 -0
- package/dist/healthMonitor.js +547 -0
- package/dist/healthMonitor.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/jobExecutor.d.ts +117 -0
- package/dist/jobExecutor.d.ts.map +1 -0
- package/dist/jobExecutor.js +458 -0
- package/dist/jobExecutor.js.map +1 -0
- package/dist/lifecycleExecutor.d.ts +54 -0
- package/dist/lifecycleExecutor.d.ts.map +1 -0
- package/dist/lifecycleExecutor.js +230 -0
- package/dist/lifecycleExecutor.js.map +1 -0
- package/dist/main.d.ts +15 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +77 -0
- package/dist/main.js.map +1 -0
- package/dist/metrics.d.ts +103 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +360 -0
- package/dist/metrics.js.map +1 -0
- package/dist/recipes/builtinRecipes.d.ts +11 -0
- package/dist/recipes/builtinRecipes.d.ts.map +1 -0
- package/dist/recipes/builtinRecipes.js +688 -0
- package/dist/recipes/builtinRecipes.js.map +1 -0
- package/dist/recipes/index.d.ts +18 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +17 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/recipes/recipeRegistry.d.ts +49 -0
- package/dist/recipes/recipeRegistry.d.ts.map +1 -0
- package/dist/recipes/recipeRegistry.js +264 -0
- package/dist/recipes/recipeRegistry.js.map +1 -0
- package/dist/recipes/types.d.ts +116 -0
- package/dist/recipes/types.d.ts.map +1 -0
- package/dist/recipes/types.js +10 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/recovery.d.ts +133 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +299 -0
- package/dist/recovery.js.map +1 -0
- package/dist/registration/apiClient.d.ts +44 -0
- package/dist/registration/apiClient.d.ts.map +1 -0
- package/dist/registration/apiClient.js +149 -0
- package/dist/registration/apiClient.js.map +1 -0
- package/dist/registration/index.d.ts +41 -0
- package/dist/registration/index.d.ts.map +1 -0
- package/dist/registration/index.js +141 -0
- package/dist/registration/index.js.map +1 -0
- package/dist/registration/machineId.d.ts +30 -0
- package/dist/registration/machineId.d.ts.map +1 -0
- package/dist/registration/machineId.js +89 -0
- package/dist/registration/machineId.js.map +1 -0
- package/dist/registration/types.d.ts +32 -0
- package/dist/registration/types.d.ts.map +1 -0
- package/dist/registration/types.js +9 -0
- package/dist/registration/types.js.map +1 -0
- package/dist/resourceGovernor.d.ts +57 -0
- package/dist/resourceGovernor.d.ts.map +1 -0
- package/dist/resourceGovernor.js +125 -0
- package/dist/resourceGovernor.js.map +1 -0
- package/dist/security/secretManager.d.ts +107 -0
- package/dist/security/secretManager.d.ts.map +1 -0
- package/dist/security/secretManager.js +361 -0
- package/dist/security/secretManager.js.map +1 -0
- package/dist/security.d.ts +134 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +470 -0
- package/dist/security.js.map +1 -0
- package/dist/storage/artifactUploader.d.ts +155 -0
- package/dist/storage/artifactUploader.d.ts.map +1 -0
- package/dist/storage/artifactUploader.js +554 -0
- package/dist/storage/artifactUploader.js.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/capabilities.d.ts +23 -0
- package/dist/utils/capabilities.d.ts.map +1 -0
- package/dist/utils/capabilities.js +200 -0
- package/dist/utils/capabilities.js.map +1 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +188 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/sdkScanner.d.ts +105 -0
- package/dist/utils/sdkScanner.d.ts.map +1 -0
- package/dist/utils/sdkScanner.js +459 -0
- package/dist/utils/sdkScanner.js.map +1 -0
- package/dist/websocketClient.d.ts +154 -0
- package/dist/websocketClient.d.ts.map +1 -0
- package/dist/websocketClient.js +422 -0
- package/dist/websocketClient.js.map +1 -0
- package/package.json +64 -0
package/dist/docker.js
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker Manager - Container management for job execution
|
|
3
|
+
*
|
|
4
|
+
* Handles Docker container lifecycle, security configuration,
|
|
5
|
+
* and resource management for isolated job execution.
|
|
6
|
+
*
|
|
7
|
+
* Enhanced with comprehensive security measures and monitoring.
|
|
8
|
+
*
|
|
9
|
+
* Requirements: 4.1, 4.2, 4.3, 4.4, 4.5
|
|
10
|
+
*/
|
|
11
|
+
import { createLogger } from './utils/logger.js';
|
|
12
|
+
import { SecurityManager } from './security.js';
|
|
13
|
+
import { spawn } from 'child_process';
|
|
14
|
+
import { promises as fs } from 'fs';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
const logger = createLogger('docker');
|
|
17
|
+
export class DockerManager {
|
|
18
|
+
config;
|
|
19
|
+
securityManager;
|
|
20
|
+
activeContainers = new Set();
|
|
21
|
+
containerTempDirs = new Map();
|
|
22
|
+
constructor(config, securityConfig) {
|
|
23
|
+
this.config = config;
|
|
24
|
+
this.securityManager = new SecurityManager(securityConfig);
|
|
25
|
+
logger.info('Docker manager initialized with enhanced security');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Clean up orphaned BuildHive containers from previous agent crashes.
|
|
29
|
+
* Should be called on startup before accepting new jobs.
|
|
30
|
+
*/
|
|
31
|
+
async cleanupOrphanedContainers() {
|
|
32
|
+
try {
|
|
33
|
+
const result = await this.executeDockerCommand([
|
|
34
|
+
'ps', '-a', '--filter', 'name=buildhive-', '--format', '{{.ID}} {{.Names}} {{.Status}}'
|
|
35
|
+
]);
|
|
36
|
+
if (result.exitCode !== 0 || !result.output.trim()) {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
const lines = result.output.trim().split('\n').filter(Boolean);
|
|
40
|
+
let cleaned = 0;
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
const [containerId, name] = line.split(' ');
|
|
43
|
+
logger.warn(`Removing orphaned container: ${name} (${containerId})`);
|
|
44
|
+
try {
|
|
45
|
+
await this.executeDockerCommand(['rm', '--force', containerId]);
|
|
46
|
+
cleaned++;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
logger.error(`Failed to remove orphaned container ${containerId}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (cleaned > 0) {
|
|
53
|
+
logger.info(`Cleaned up ${cleaned} orphaned container(s)`);
|
|
54
|
+
}
|
|
55
|
+
return cleaned;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
logger.error('Failed to clean up orphaned containers:', error);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if Docker is available and running
|
|
64
|
+
*/
|
|
65
|
+
async checkDockerAvailability() {
|
|
66
|
+
try {
|
|
67
|
+
const result = await this.executeDockerCommand(['version', '--format', 'json']);
|
|
68
|
+
return result.exitCode === 0;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
logger.error('Docker is not available:', error);
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Pull Docker image
|
|
77
|
+
*/
|
|
78
|
+
async pullImage(image) {
|
|
79
|
+
// Check if image exists locally first
|
|
80
|
+
try {
|
|
81
|
+
const inspectResult = await this.executeDockerCommand(['image', 'inspect', image]);
|
|
82
|
+
if (inspectResult.exitCode === 0) {
|
|
83
|
+
logger.info(`Image already cached locally: ${image}`);
|
|
84
|
+
return; // Skip pull
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Image not found locally, proceed to pull
|
|
89
|
+
}
|
|
90
|
+
logger.info(`Pulling Docker image: ${image}`);
|
|
91
|
+
try {
|
|
92
|
+
const result = await this.executeDockerCommand(['pull', image]);
|
|
93
|
+
if (result.exitCode !== 0) {
|
|
94
|
+
throw new Error(`Failed to pull image ${image}: ${result.error}`);
|
|
95
|
+
}
|
|
96
|
+
logger.info(`Successfully pulled image: ${image}`);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
logger.error(`Failed to pull image ${image}:`, error);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Create a Docker container with enhanced security configuration
|
|
105
|
+
*/
|
|
106
|
+
async createContainer(containerConfig) {
|
|
107
|
+
const containerId = `buildhive-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
108
|
+
logger.info(`Creating secure container: ${containerId}`);
|
|
109
|
+
try {
|
|
110
|
+
// Validate image security first
|
|
111
|
+
const imageViolations = await this.securityManager.validateImageSecurity(containerConfig.image);
|
|
112
|
+
if (imageViolations.some(v => v.severity === 'critical')) {
|
|
113
|
+
logger.warn(`Image security violations:`, imageViolations.filter(v => v.severity === 'critical').map(v => v.message));
|
|
114
|
+
throw new Error(`Image failed security validation: ${imageViolations.filter(v => v.severity === 'critical').map(v => v.message).join(', ')}`);
|
|
115
|
+
}
|
|
116
|
+
// Validate container configuration
|
|
117
|
+
const configViolations = await this.securityManager.validateContainerConfig({
|
|
118
|
+
...containerConfig,
|
|
119
|
+
containerId,
|
|
120
|
+
memoryLimit: this.config.memoryLimit,
|
|
121
|
+
cpuLimit: this.config.cpuLimit,
|
|
122
|
+
networkMode: this.config.networkMode
|
|
123
|
+
});
|
|
124
|
+
const criticalViolations = configViolations.filter(v => v.severity === 'critical');
|
|
125
|
+
if (criticalViolations.length > 0) {
|
|
126
|
+
logger.warn(`Container security violations:`, criticalViolations.map(v => v.message));
|
|
127
|
+
throw new Error(`Container configuration failed security validation: ${criticalViolations.map(v => v.message).join(', ')}`);
|
|
128
|
+
}
|
|
129
|
+
// Create secure temporary directory
|
|
130
|
+
const tempDir = await this.securityManager.createSecureTempDir(containerId);
|
|
131
|
+
this.containerTempDirs.set(containerId, tempDir);
|
|
132
|
+
const dockerArgs = [
|
|
133
|
+
'create',
|
|
134
|
+
'--name', containerId,
|
|
135
|
+
// No --rm: we handle cleanup explicitly via stopContainer/removeContainer
|
|
136
|
+
];
|
|
137
|
+
// Add enhanced security arguments, filtering out tmpfs mounts that
|
|
138
|
+
// conflict with explicit volume mounts (e.g. /workspace is both a
|
|
139
|
+
// volume mount from the job and a tmpfs from allowedWritePaths)
|
|
140
|
+
const mountedPaths = new Set(containerConfig.volumeMounts.map(m => m.containerPath));
|
|
141
|
+
const securityArgs = this.securityManager.generateSecureDockerArgs(containerId)
|
|
142
|
+
.filter((arg, i, arr) => {
|
|
143
|
+
// Remove --tmpfs entries whose path conflicts with an explicit volume mount
|
|
144
|
+
if (arg === '--tmpfs' && i + 1 < arr.length) {
|
|
145
|
+
const tmpfsPath = arr[i + 1].split(':')[0];
|
|
146
|
+
return !mountedPaths.has(tmpfsPath);
|
|
147
|
+
}
|
|
148
|
+
// Also remove the value after a filtered --tmpfs
|
|
149
|
+
if (i > 0 && arr[i - 1] === '--tmpfs') {
|
|
150
|
+
const tmpfsPath = arg.split(':')[0];
|
|
151
|
+
return !mountedPaths.has(tmpfsPath);
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
});
|
|
155
|
+
dockerArgs.push(...securityArgs);
|
|
156
|
+
// Add basic configuration
|
|
157
|
+
dockerArgs.push('--workdir', containerConfig.workDir);
|
|
158
|
+
// Add volume mounts with security validation
|
|
159
|
+
for (const mount of containerConfig.volumeMounts) {
|
|
160
|
+
// Use secure temp directory for writable mounts
|
|
161
|
+
const hostPath = mount.hostPath;
|
|
162
|
+
const mountStr = `${hostPath}:${mount.containerPath}${mount.readOnly ? ':ro' : ''}`;
|
|
163
|
+
dockerArgs.push('--volume', mountStr);
|
|
164
|
+
}
|
|
165
|
+
// Add environment variables
|
|
166
|
+
for (const [key, value] of Object.entries(containerConfig.environment)) {
|
|
167
|
+
dockerArgs.push('--env', `${key}=${value}`);
|
|
168
|
+
}
|
|
169
|
+
// Add the image and a keep-alive command so the container stays running
|
|
170
|
+
dockerArgs.push(containerConfig.image);
|
|
171
|
+
dockerArgs.push('tail', '-f', '/dev/null');
|
|
172
|
+
// Execute docker create command
|
|
173
|
+
const result = await this.executeDockerCommand(dockerArgs);
|
|
174
|
+
if (result.exitCode !== 0) {
|
|
175
|
+
throw new Error(`Failed to create container: ${result.error}`);
|
|
176
|
+
}
|
|
177
|
+
this.activeContainers.add(containerId);
|
|
178
|
+
logger.info(`Secure container created successfully: ${containerId}`);
|
|
179
|
+
return containerId;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
logger.error(`Failed to create secure container ${containerId}:`, error);
|
|
183
|
+
// Cleanup temp directory on failure
|
|
184
|
+
const tempDir = this.containerTempDirs.get(containerId);
|
|
185
|
+
if (tempDir) {
|
|
186
|
+
await this.securityManager.cleanupSecureTempDir(tempDir);
|
|
187
|
+
this.containerTempDirs.delete(containerId);
|
|
188
|
+
}
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Start a Docker container with security monitoring
|
|
194
|
+
*/
|
|
195
|
+
async startContainer(containerId) {
|
|
196
|
+
logger.info(`Starting secure container: ${containerId}`);
|
|
197
|
+
try {
|
|
198
|
+
const result = await this.executeDockerCommand(['start', containerId]);
|
|
199
|
+
if (result.exitCode !== 0) {
|
|
200
|
+
throw new Error(`Failed to start container ${containerId}: ${result.error}`);
|
|
201
|
+
}
|
|
202
|
+
// Start security monitoring
|
|
203
|
+
await this.securityManager.startResourceMonitoring(containerId);
|
|
204
|
+
logger.info(`Secure container started successfully: ${containerId}`);
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
logger.error(`Failed to start secure container ${containerId}:`, error);
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Execute a command in a running container
|
|
213
|
+
*/
|
|
214
|
+
async executeCommand(containerId, command, options = {}) {
|
|
215
|
+
logger.info(`Executing command in container ${containerId}: ${command}`);
|
|
216
|
+
try {
|
|
217
|
+
const dockerArgs = [
|
|
218
|
+
'exec',
|
|
219
|
+
'--interactive',
|
|
220
|
+
containerId,
|
|
221
|
+
'sh', '-c', command
|
|
222
|
+
];
|
|
223
|
+
const result = await this.executeDockerCommand(dockerArgs, {
|
|
224
|
+
timeout: options.timeout,
|
|
225
|
+
onOutput: options.onOutput
|
|
226
|
+
});
|
|
227
|
+
logger.info(`Command execution completed in container ${containerId} (exit code: ${result.exitCode})`);
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
logger.error(`Failed to execute command in container ${containerId}:`, error);
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Stop a running container
|
|
237
|
+
*/
|
|
238
|
+
async stopContainer(containerId, timeout = 10) {
|
|
239
|
+
logger.info(`Stopping container: ${containerId}`);
|
|
240
|
+
try {
|
|
241
|
+
const result = await this.executeDockerCommand(['stop', '--time', timeout.toString(), containerId]);
|
|
242
|
+
if (result.exitCode !== 0) {
|
|
243
|
+
logger.warn(`Failed to stop container gracefully, forcing: ${containerId}`);
|
|
244
|
+
await this.executeDockerCommand(['kill', containerId]);
|
|
245
|
+
}
|
|
246
|
+
logger.info(`Container stopped: ${containerId}`);
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
logger.error(`Failed to stop container ${containerId}:`, error);
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Remove a container with security cleanup
|
|
255
|
+
*/
|
|
256
|
+
async removeContainer(containerId) {
|
|
257
|
+
logger.info(`Removing secure container: ${containerId}`);
|
|
258
|
+
try {
|
|
259
|
+
// Stop security monitoring
|
|
260
|
+
this.securityManager.stopResourceMonitoring(containerId);
|
|
261
|
+
// First try to stop the container if it's running
|
|
262
|
+
await this.stopContainer(containerId);
|
|
263
|
+
// Remove the container
|
|
264
|
+
const result = await this.executeDockerCommand(['rm', '--force', containerId]);
|
|
265
|
+
if (result.exitCode !== 0) {
|
|
266
|
+
logger.warn(`Failed to remove container ${containerId}: ${result.error}`);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
logger.info(`Container removed: ${containerId}`);
|
|
270
|
+
}
|
|
271
|
+
// Cleanup secure temp directory
|
|
272
|
+
const tempDir = this.containerTempDirs.get(containerId);
|
|
273
|
+
if (tempDir) {
|
|
274
|
+
await this.securityManager.cleanupSecureTempDir(tempDir);
|
|
275
|
+
this.containerTempDirs.delete(containerId);
|
|
276
|
+
}
|
|
277
|
+
this.activeContainers.delete(containerId);
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
logger.error(`Failed to remove secure container ${containerId}:`, error);
|
|
281
|
+
// Don't throw here, as this is cleanup
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Copy file from container to host
|
|
286
|
+
*/
|
|
287
|
+
async copyFromContainer(containerId, containerPath, hostPath) {
|
|
288
|
+
logger.info(`Copying from container ${containerId}: ${containerPath} -> ${hostPath}`);
|
|
289
|
+
try {
|
|
290
|
+
// Ensure host directory exists
|
|
291
|
+
const hostDir = join(hostPath, '..');
|
|
292
|
+
await fs.mkdir(hostDir, { recursive: true });
|
|
293
|
+
const result = await this.executeDockerCommand([
|
|
294
|
+
'cp',
|
|
295
|
+
`${containerId}:${containerPath}`,
|
|
296
|
+
hostPath
|
|
297
|
+
]);
|
|
298
|
+
if (result.exitCode !== 0) {
|
|
299
|
+
throw new Error(`Failed to copy from container: ${result.error}`);
|
|
300
|
+
}
|
|
301
|
+
logger.info(`Successfully copied from container: ${containerPath}`);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
logger.error(`Failed to copy from container ${containerId}:`, error);
|
|
305
|
+
throw error;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get container logs
|
|
310
|
+
*/
|
|
311
|
+
async getContainerLogs(containerId) {
|
|
312
|
+
try {
|
|
313
|
+
const result = await this.executeDockerCommand(['logs', containerId]);
|
|
314
|
+
return result.output;
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
logger.error(`Failed to get logs for container ${containerId}:`, error);
|
|
318
|
+
return '';
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Get security violations for monitoring
|
|
323
|
+
*/
|
|
324
|
+
getSecurityViolations() {
|
|
325
|
+
return this.securityManager.getViolations();
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Get resource usage for a container
|
|
329
|
+
*/
|
|
330
|
+
async getResourceUsage(containerId) {
|
|
331
|
+
return await this.securityManager.getResourceUsage(containerId);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Clean up all active containers with security cleanup
|
|
335
|
+
*/
|
|
336
|
+
async cleanup() {
|
|
337
|
+
logger.info('Cleaning up secure Docker manager...');
|
|
338
|
+
const containerIds = Array.from(this.activeContainers);
|
|
339
|
+
for (const containerId of containerIds) {
|
|
340
|
+
await this.removeContainer(containerId);
|
|
341
|
+
}
|
|
342
|
+
// Cleanup security manager
|
|
343
|
+
this.securityManager.cleanup();
|
|
344
|
+
this.activeContainers.clear();
|
|
345
|
+
this.containerTempDirs.clear();
|
|
346
|
+
logger.info('Secure Docker manager cleanup completed');
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Execute a Docker command
|
|
350
|
+
*/
|
|
351
|
+
async executeDockerCommand(args, options = {}) {
|
|
352
|
+
return new Promise((resolve, reject) => {
|
|
353
|
+
const child = spawn('docker', args, {
|
|
354
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
355
|
+
});
|
|
356
|
+
let output = '';
|
|
357
|
+
let error = '';
|
|
358
|
+
let outputTruncated = false;
|
|
359
|
+
const MAX_OUTPUT_SIZE = 10 * 1024 * 1024; // 10MB
|
|
360
|
+
let timeoutId = null;
|
|
361
|
+
// Set up timeout if specified
|
|
362
|
+
if (options.timeout) {
|
|
363
|
+
timeoutId = setTimeout(() => {
|
|
364
|
+
child.kill('SIGKILL');
|
|
365
|
+
reject(new Error(`Command timed out after ${options.timeout}ms`));
|
|
366
|
+
}, options.timeout);
|
|
367
|
+
}
|
|
368
|
+
// Collect stdout
|
|
369
|
+
child.stdout.on('data', (data) => {
|
|
370
|
+
const chunk = data.toString();
|
|
371
|
+
if (output.length < MAX_OUTPUT_SIZE) {
|
|
372
|
+
output += chunk;
|
|
373
|
+
}
|
|
374
|
+
else if (!outputTruncated) {
|
|
375
|
+
output += '\n[OUTPUT TRUNCATED - exceeded 10MB limit]';
|
|
376
|
+
outputTruncated = true;
|
|
377
|
+
}
|
|
378
|
+
if (options.onOutput) {
|
|
379
|
+
options.onOutput(chunk);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
// Collect stderr
|
|
383
|
+
child.stderr.on('data', (data) => {
|
|
384
|
+
const chunk = data.toString();
|
|
385
|
+
error += chunk;
|
|
386
|
+
if (options.onOutput) {
|
|
387
|
+
options.onOutput(chunk);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
// Handle process completion
|
|
391
|
+
child.on('close', (code) => {
|
|
392
|
+
if (timeoutId) {
|
|
393
|
+
clearTimeout(timeoutId);
|
|
394
|
+
}
|
|
395
|
+
resolve({
|
|
396
|
+
exitCode: code || 0,
|
|
397
|
+
output: output.trim(),
|
|
398
|
+
error: error.trim()
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
// Handle process errors
|
|
402
|
+
child.on('error', (err) => {
|
|
403
|
+
if (timeoutId) {
|
|
404
|
+
clearTimeout(timeoutId);
|
|
405
|
+
}
|
|
406
|
+
reject(err);
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=docker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAqC,MAAM,eAAe,CAAC;AACnF,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AAwBtC,MAAM,OAAO,aAAa;IAChB,MAAM,CAAe;IACrB,eAAe,CAAkB;IACjC,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEtD,YAAY,MAAoB,EAAE,cAA8B;QAC9D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAC,cAAc,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IACnE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,yBAAyB;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC;gBAC7C,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,gCAAgC;aACxF,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnD,OAAO,CAAC,CAAC;YACX,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC/D,IAAI,OAAO,GAAG,CAAC,CAAC;YAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC5C,MAAM,CAAC,IAAI,CAAC,gCAAgC,IAAI,KAAK,WAAW,GAAG,CAAC,CAAC;gBACrE,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;oBAChE,OAAO,EAAE,CAAC;gBACZ,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,CAAC,KAAK,CAAC,uCAAuC,WAAW,EAAE,CAAC,CAAC;gBACrE,CAAC;YACH,CAAC;YAED,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAChB,MAAM,CAAC,IAAI,CAAC,cAAc,OAAO,wBAAwB,CAAC,CAAC;YAC7D,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;YAC/D,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,uBAAuB;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;YAChF,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YAChD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,KAAa;QAC3B,sCAAsC;QACtC,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;YACnF,IAAI,aAAa,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAC;gBACtD,OAAO,CAAC,YAAY;YACtB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;QAE9C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;YAEhE,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACpE,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,8BAA8B,KAAK,EAAE,CAAC,CAAC;QAErD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,wBAAwB,KAAK,GAAG,EAAE,KAAK,CAAC,CAAC;YACtD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,eAAgC;QACpD,MAAM,WAAW,GAAG,aAAa,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAEzF,MAAM,CAAC,IAAI,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC;YACH,gCAAgC;YAChC,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,qBAAqB,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAChG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,EAAE,CAAC;gBACzD,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;gBACtH,MAAM,IAAI,KAAK,CAAC,qCAAqC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChJ,CAAC;YAED,mCAAmC;YACnC,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,uBAAuB,CAAC;gBAC1E,GAAG,eAAe;gBAClB,WAAW;gBACX,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW;gBACpC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAC9B,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW;aACrC,CAAC,CAAC;YAEH,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;YACnF,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,CAAC,IAAI,CAAC,gCAAgC,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;gBACtF,MAAM,IAAI,KAAK,CAAC,uDAAuD,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9H,CAAC;YAED,oCAAoC;YACpC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;YAC5E,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAEjD,MAAM,UAAU,GAAG;gBACjB,QAAQ;gBACR,QAAQ,EAAE,WAAW;gBACrB,0EAA0E;aAC3E,CAAC;YAEF,mEAAmE;YACnE,kEAAkE;YAClE,gEAAgE;YAChE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;YACrF,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,wBAAwB,CAAC,WAAW,CAAC;iBAC5E,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;gBACtB,4EAA4E;gBAC5E,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;oBAC5C,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC3C,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACtC,CAAC;gBACD,iDAAiD;gBACjD,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;oBACtC,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBACpC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACtC,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;YACL,UAAU,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;YAEjC,0BAA0B;YAC1B,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;YAEtD,6CAA6C;YAC7C,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,YAAY,EAAE,CAAC;gBACjD,gDAAgD;gBAChD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;gBAChC,MAAM,QAAQ,GAAG,GAAG,QAAQ,IAAI,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACpF,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACxC,CAAC;YAED,4BAA4B;YAC5B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC;gBACvE,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;YAC9C,CAAC;YAED,wEAAwE;YACxE,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YACvC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;YAE3C,gCAAgC;YAChC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;YAE3D,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACjE,CAAC;YAED,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,0CAA0C,WAAW,EAAE,CAAC,CAAC;YAErE,OAAO,WAAW,CAAC;QAErB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,qCAAqC,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YAEzE,oCAAoC;YACpC,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACxD,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;gBACzD,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC7C,CAAC;YAED,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,WAAmB;QACtC,MAAM,CAAC,IAAI,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;YAEvE,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,6BAA6B,WAAW,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YAC/E,CAAC;YAED,4BAA4B;YAC5B,MAAM,IAAI,CAAC,eAAe,CAAC,uBAAuB,CAAC,WAAW,CAAC,CAAC;YAEhE,MAAM,CAAC,IAAI,CAAC,0CAA0C,WAAW,EAAE,CAAC,CAAC;QAEvE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,oCAAoC,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YACxE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAClB,WAAmB,EACnB,OAAe,EACf,UAA4B,EAAE;QAE9B,MAAM,CAAC,IAAI,CAAC,kCAAkC,WAAW,KAAK,OAAO,EAAE,CAAC,CAAC;QAEzE,IAAI,CAAC;YACH,MAAM,UAAU,GAAG;gBACjB,MAAM;gBACN,eAAe;gBACf,WAAW;gBACX,IAAI,EAAE,IAAI,EAAE,OAAO;aACpB,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE;gBACzD,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;aAC3B,CAAC,CAAC;YAEH,MAAM,CAAC,IAAI,CAAC,4CAA4C,WAAW,gBAAgB,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC;YAEvG,OAAO,MAAM,CAAC;QAEhB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,0CAA0C,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YAC9E,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,UAAkB,EAAE;QAC3D,MAAM,CAAC,IAAI,CAAC,uBAAuB,WAAW,EAAE,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;YAEpG,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,CAAC,iDAAiD,WAAW,EAAE,CAAC,CAAC;gBAC5E,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;YACzD,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,sBAAsB,WAAW,EAAE,CAAC,CAAC;QAEnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,4BAA4B,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YAChE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,WAAmB;QACvC,MAAM,CAAC,IAAI,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC;YACH,2BAA2B;YAC3B,IAAI,CAAC,eAAe,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;YAEzD,kDAAkD;YAClD,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;YAEtC,uBAAuB;YACvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;YAE/E,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,CAAC,8BAA8B,WAAW,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YAC5E,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,sBAAsB,WAAW,EAAE,CAAC,CAAC;YACnD,CAAC;YAED,gCAAgC;YAChC,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACxD,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;gBACzD,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC7C,CAAC;YAED,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,qCAAqC,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YACzE,uCAAuC;QACzC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CAAC,WAAmB,EAAE,aAAqB,EAAE,QAAgB;QAClF,MAAM,CAAC,IAAI,CAAC,0BAA0B,WAAW,KAAK,aAAa,OAAO,QAAQ,EAAE,CAAC,CAAC;QAEtF,IAAI,CAAC;YACH,+BAA+B;YAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACrC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAE7C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC;gBAC7C,IAAI;gBACJ,GAAG,WAAW,IAAI,aAAa,EAAE;gBACjC,QAAQ;aACT,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACpE,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,uCAAuC,aAAa,EAAE,CAAC,CAAC;QAEtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,iCAAiC,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YACrE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,WAAmB;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;YACtE,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,oCAAoC,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YACxE,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,qBAAqB;QACnB,OAAO,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,WAAmB;QACxC,OAAO,MAAM,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QAEpD,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAEvD,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QAC1C,CAAC;QAED,2BAA2B;QAC3B,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;QAE/B,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACzD,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB,CAChC,IAAc,EACd,UAA4B,EAAE;QAE9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE;gBAClC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAChC,CAAC,CAAC;YAEH,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,KAAK,GAAG,EAAE,CAAC;YACf,IAAI,eAAe,GAAG,KAAK,CAAC;YAC5B,MAAM,eAAe,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;YACjD,IAAI,SAAS,GAA0B,IAAI,CAAC;YAE5C,8BAA8B;YAC9B,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;oBAC1B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACtB,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;gBACpE,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;YAED,iBAAiB;YACjB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;gBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC9B,IAAI,MAAM,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;oBACpC,MAAM,IAAI,KAAK,CAAC;gBAClB,CAAC;qBAAM,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC5B,MAAM,IAAI,4CAA4C,CAAC;oBACvD,eAAe,GAAG,IAAI,CAAC;gBACzB,CAAC;gBAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;oBACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,iBAAiB;YACjB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;gBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC9B,KAAK,IAAI,KAAK,CAAC;gBAEf,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;oBACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,4BAA4B;YAC5B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAmB,EAAE,EAAE;gBACxC,IAAI,SAAS,EAAE,CAAC;oBACd,YAAY,CAAC,SAAS,CAAC,CAAC;gBAC1B,CAAC;gBAED,OAAO,CAAC;oBACN,QAAQ,EAAE,IAAI,IAAI,CAAC;oBACnB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;oBACrB,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE;iBACpB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,wBAAwB;YACxB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;gBAC/B,IAAI,SAAS,EAAE,CAAC;oBACd,YAAY,CAAC,SAAS,CAAC,CAAC;gBAC1B,CAAC;gBAED,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Job Executor
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the full enhanced pipeline with recipe awareness:
|
|
5
|
+
* 1. Acceptance check (should we accept this job?)
|
|
6
|
+
* 2. Resource governance check (do we have resources?)
|
|
7
|
+
* 3. Recipe detection (what kind of project is this?)
|
|
8
|
+
* 4. Recipe application (merge recipe config into job)
|
|
9
|
+
* 5. Executor selection (Docker vs Native)
|
|
10
|
+
* 6. Cache setup (mount cache volumes)
|
|
11
|
+
* 7. Lifecycle execution (setup -> build -> teardown)
|
|
12
|
+
* 8. Cache save (update metadata)
|
|
13
|
+
* 9. Result reporting
|
|
14
|
+
*
|
|
15
|
+
* This module does NOT modify the existing JobExecutor. It wraps
|
|
16
|
+
* the new subsystems (RecipeRegistry, CacheManager, AcceptanceChecker,
|
|
17
|
+
* ResourceGovernor, ExecutorFactory, LifecycleExecutor) into a single
|
|
18
|
+
* cohesive pipeline.
|
|
19
|
+
*/
|
|
20
|
+
import { RecipeRegistry } from './recipes/recipeRegistry.js';
|
|
21
|
+
import { CacheManager } from './cacheManager.js';
|
|
22
|
+
import { AcceptanceChecker } from './acceptanceChecker.js';
|
|
23
|
+
import { ResourceGovernor, ResourceSnapshot } from './resourceGovernor.js';
|
|
24
|
+
export interface EnhancedJobRequest {
|
|
25
|
+
id: string;
|
|
26
|
+
repository: string;
|
|
27
|
+
buildCommand: string;
|
|
28
|
+
dockerImage?: string;
|
|
29
|
+
environment?: Record<string, string>;
|
|
30
|
+
workDir: string;
|
|
31
|
+
artifacts?: string[];
|
|
32
|
+
/** Optional recipe name override (skip auto-detection). */
|
|
33
|
+
recipe?: string;
|
|
34
|
+
/** Per-job execution mode override. */
|
|
35
|
+
executionMode?: 'docker' | 'native' | 'auto';
|
|
36
|
+
}
|
|
37
|
+
export interface EnhancedJobCallbacks {
|
|
38
|
+
onProgress?: (percent: number, stage: string) => void;
|
|
39
|
+
onLog?: (log: string) => void;
|
|
40
|
+
}
|
|
41
|
+
export interface EnhancedExecutionResult {
|
|
42
|
+
success: boolean;
|
|
43
|
+
exitCode: number;
|
|
44
|
+
logs: string;
|
|
45
|
+
artifacts: string[];
|
|
46
|
+
durationMs: number;
|
|
47
|
+
/** Name of the recipe that was applied (if any). */
|
|
48
|
+
recipe?: string;
|
|
49
|
+
cacheHit: boolean;
|
|
50
|
+
executionMode: 'docker' | 'native';
|
|
51
|
+
lifecycleResults?: {
|
|
52
|
+
setupResults: any[];
|
|
53
|
+
teardownResults: any[];
|
|
54
|
+
};
|
|
55
|
+
/** Present when the job was rejected before execution. */
|
|
56
|
+
rejection?: {
|
|
57
|
+
reason: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export interface EnhancedJobExecutorConfig {
|
|
61
|
+
executionMode: 'docker' | 'native' | 'auto';
|
|
62
|
+
dockerAvailable: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Collect resource snapshot. Callers may provide an override (e.g. in tests).
|
|
66
|
+
* The default produces a "healthy" snapshot.
|
|
67
|
+
*/
|
|
68
|
+
export type ResourceSnapshotProvider = () => ResourceSnapshot;
|
|
69
|
+
export declare class EnhancedJobExecutor {
|
|
70
|
+
private recipeRegistry;
|
|
71
|
+
private cacheManager;
|
|
72
|
+
private acceptanceChecker;
|
|
73
|
+
private resourceGovernor;
|
|
74
|
+
private config;
|
|
75
|
+
private lifecycleExecutor;
|
|
76
|
+
private snapshotProvider;
|
|
77
|
+
constructor(recipeRegistry: RecipeRegistry, cacheManager: CacheManager, acceptanceChecker: AcceptanceChecker, resourceGovernor: ResourceGovernor, config: EnhancedJobExecutorConfig, snapshotProvider?: ResourceSnapshotProvider);
|
|
78
|
+
executeJob(job: EnhancedJobRequest, callbacks?: EnhancedJobCallbacks): Promise<EnhancedExecutionResult>;
|
|
79
|
+
private rejectionResult;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=enhancedJobExecutor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enhancedJobExecutor.d.ts","sourceRoot":"","sources":["../src/enhancedJobExecutor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAoB,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAgB,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQ3E,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,aAAa,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC9C;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACnC,gBAAgB,CAAC,EAAE;QACjB,YAAY,EAAE,GAAG,EAAE,CAAC;QACpB,eAAe,EAAE,GAAG,EAAE,CAAC;KACxB,CAAC;IACF,0DAA0D;IAC1D,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC5C,eAAe,EAAE,OAAO,CAAC;CAC1B;AAMD;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,MAAM,gBAAgB,CAAC;AAa9D,qBAAa,mBAAmB;IAK5B,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,iBAAiB;IACzB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,MAAM;IARhB,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,gBAAgB,CAA2B;gBAGzC,cAAc,EAAE,cAAc,EAC9B,YAAY,EAAE,YAAY,EAC1B,iBAAiB,EAAE,iBAAiB,EACpC,gBAAgB,EAAE,gBAAgB,EAClC,MAAM,EAAE,yBAAyB,EACzC,gBAAgB,CAAC,EAAE,wBAAwB;IAUvC,UAAU,CACd,GAAG,EAAE,kBAAkB,EACvB,SAAS,CAAC,EAAE,oBAAoB,GAC/B,OAAO,CAAC,uBAAuB,CAAC;IAwLnC,OAAO,CAAC,eAAe;CAgBxB"}
|