This commit is contained in:
Raven Scott
2025-11-24 17:05:20 -05:00
parent 0cf2df3c76
commit 07cdbf293e
3 changed files with 2154 additions and 48 deletions
+261
View File
@@ -638,6 +638,267 @@ swarm.on('connection', (peer) => {
};
break;
case 'getSystemInfo':
console.log('[INFO] Handling \'getSystemInfo\' command');
try {
const [info, version] = await Promise.all([
docker.info(),
docker.version()
]);
response = {
type: 'systemInfo',
data: { info, version }
};
} catch (error) {
console.error(`[ERROR] Failed to get system info: ${error.message}`);
response = { error: 'Failed to get system info' };
}
break;
case 'listImages':
console.log('[INFO] Handling \'listImages\' command');
try {
const images = await docker.listImages({ all: true });
// Get container usage for each image
const containers = await docker.listContainers({ all: true });
const imageUsage = {};
containers.forEach(container => {
const imageId = container.ImageID;
if (!imageUsage[imageId]) {
imageUsage[imageId] = [];
}
imageUsage[imageId].push({
id: container.Id,
name: container.Names[0]?.replace(/^\//, '') || container.Id.substring(0, 12),
state: container.State
});
});
const imagesWithUsage = images.map(image => ({
...image,
usage: imageUsage[image.Id] || []
}));
response = { type: 'images', data: imagesWithUsage };
} catch (error) {
console.error(`[ERROR] Failed to list images: ${error.message}`);
response = { error: 'Failed to list images' };
}
break;
case 'pullImage':
console.log(`[INFO] Handling 'pullImage' command for image: ${parsedData.args.image}`);
try {
const imageName = validation.sanitizeString(parsedData.args.image, 255);
if (!imageName || !validation.isValidImageName(imageName)) {
throw new Error('Invalid image name');
}
const pullStream = await docker.pull(imageName);
await new Promise((resolve, reject) => {
docker.modem.followProgress(pullStream, (err) => {
if (err) reject(err);
else resolve();
});
});
response = { success: true, message: `Image "${imageName}" pulled successfully` };
} catch (error) {
console.error(`[ERROR] Failed to pull image: ${error.message}`);
response = { error: `Failed to pull image: ${error.message}` };
}
break;
case 'removeImage':
console.log(`[INFO] Handling 'removeImage' command for image: ${parsedData.args.id}`);
try {
const image = docker.getImage(parsedData.args.id);
await image.remove({ force: parsedData.args.force || false });
response = { success: true, message: `Image ${parsedData.args.id} removed` };
} catch (error) {
console.error(`[ERROR] Failed to remove image: ${error.message}`);
response = { error: `Failed to remove image: ${error.message}` };
}
break;
case 'inspectImage':
console.log(`[INFO] Handling 'inspectImage' command for image: ${parsedData.args.id}`);
try {
const image = docker.getImage(parsedData.args.id);
const imageData = await image.inspect();
response = { type: 'imageConfig', data: imageData };
} catch (error) {
console.error(`[ERROR] Failed to inspect image: ${error.message}`);
response = { error: `Failed to inspect image: ${error.message}` };
}
break;
case 'listNetworks':
console.log('[INFO] Handling \'listNetworks\' command');
try {
const networks = await docker.listNetworks();
// Get container usage for each network
const containers = await docker.listContainers({ all: true });
const networkUsage = {};
containers.forEach(container => {
if (container.NetworkSettings && container.NetworkSettings.Networks) {
Object.keys(container.NetworkSettings.Networks).forEach(networkName => {
if (!networkUsage[networkName]) {
networkUsage[networkName] = [];
}
networkUsage[networkName].push({
id: container.Id,
name: container.Names[0]?.replace(/^\//, '') || container.Id.substring(0, 12),
state: container.State
});
});
}
});
const networksWithUsage = networks.map(network => ({
...network,
usage: networkUsage[network.Name] || []
}));
response = { type: 'networks', data: networksWithUsage };
} catch (error) {
console.error(`[ERROR] Failed to list networks: ${error.message}`);
response = { error: 'Failed to list networks' };
}
break;
case 'createNetwork':
console.log('[INFO] Handling \'createNetwork\' command');
try {
const args = parsedData.args;
const networkConfig = {
Name: validation.sanitizeString(args.name, 128),
Driver: args.driver || 'bridge',
CheckDuplicate: true
};
if (args.subnet) networkConfig.IPAM = {
Config: [{ Subnet: args.subnet }]
};
if (args.options && typeof args.options === 'object') {
networkConfig.Options = args.options;
}
const network = await docker.createNetwork(networkConfig);
response = { success: true, message: `Network "${args.name}" created successfully`, data: network.id };
} catch (error) {
console.error(`[ERROR] Failed to create network: ${error.message}`);
response = { error: `Failed to create network: ${error.message}` };
}
break;
case 'removeNetwork':
console.log(`[INFO] Handling 'removeNetwork' command for network: ${parsedData.args.id}`);
try {
const network = docker.getNetwork(parsedData.args.id);
await network.remove();
response = { success: true, message: `Network ${parsedData.args.id} removed` };
} catch (error) {
console.error(`[ERROR] Failed to remove network: ${error.message}`);
response = { error: `Failed to remove network: ${error.message}` };
}
break;
case 'inspectNetwork':
console.log(`[INFO] Handling 'inspectNetwork' command for network: ${parsedData.args.id}`);
try {
const network = docker.getNetwork(parsedData.args.id);
const networkData = await network.inspect();
response = { type: 'networkConfig', data: networkData };
} catch (error) {
console.error(`[ERROR] Failed to inspect network: ${error.message}`);
response = { error: `Failed to inspect network: ${error.message}` };
}
break;
case 'listVolumes':
console.log('[INFO] Handling \'listVolumes\' command');
try {
const volumes = await docker.listVolumes();
// Get container usage for each volume
const containers = await docker.listContainers({ all: true });
const volumeUsage = {};
containers.forEach(container => {
if (container.Mounts) {
container.Mounts.forEach(mount => {
if (mount.Type === 'volume' && mount.Name) {
if (!volumeUsage[mount.Name]) {
volumeUsage[mount.Name] = [];
}
volumeUsage[mount.Name].push({
id: container.Id,
name: container.Names[0]?.replace(/^\//, '') || container.Id.substring(0, 12),
state: container.State,
destination: mount.Destination
});
}
});
}
});
const volumesWithUsage = (volumes.Volumes || []).map(volume => ({
...volume,
usage: volumeUsage[volume.Name] || []
}));
response = { type: 'volumes', data: volumesWithUsage };
} catch (error) {
console.error(`[ERROR] Failed to list volumes: ${error.message}`);
response = { error: 'Failed to list volumes' };
}
break;
case 'createVolume':
console.log('[INFO] Handling \'createVolume\' command');
try {
const args = parsedData.args;
const volumeConfig = {
Name: validation.sanitizeString(args.name, 128)
};
if (args.driver) volumeConfig.Driver = args.driver;
if (args.options && typeof args.options === 'object') {
volumeConfig.DriverOpts = args.options;
};
const volume = await docker.createVolume(volumeConfig);
response = { success: true, message: `Volume "${args.name}" created successfully`, data: volume.name };
} catch (error) {
console.error(`[ERROR] Failed to create volume: ${error.message}`);
response = { error: `Failed to create volume: ${error.message}` };
}
break;
case 'removeVolume':
console.log(`[INFO] Handling 'removeVolume' command for volume: ${parsedData.args.name}`);
try {
const volume = docker.getVolume(parsedData.args.name);
await volume.remove();
response = { success: true, message: `Volume ${parsedData.args.name} removed` };
} catch (error) {
console.error(`[ERROR] Failed to remove volume: ${error.message}`);
response = { error: `Failed to remove volume: ${error.message}` };
}
break;
case 'inspectVolume':
console.log(`[INFO] Handling 'inspectVolume' command for volume: ${parsedData.args.name}`);
try {
const volume = docker.getVolume(parsedData.args.name);
const volumeData = await volume.inspect();
response = { type: 'volumeConfig', data: volumeData };
} catch (error) {
console.error(`[ERROR] Failed to inspect volume: ${error.message}`);
response = { error: `Failed to inspect volume: ${error.message}` };
}
break;
default:
console.warn(`[WARN] Unknown command: ${parsedData.command}`);
return;