298 lines
7.9 KiB
JavaScript
298 lines
7.9 KiB
JavaScript
/**
|
|
* Container configuration builder utilities
|
|
* Extracted from deployContainer to improve modularity
|
|
*/
|
|
|
|
import * as validation from './validation.js';
|
|
|
|
/**
|
|
* Build basic container configuration
|
|
* @param {Object} args - Deployment arguments
|
|
* @returns {Object} - Container configuration
|
|
*/
|
|
export function buildBasicConfig(args) {
|
|
const containerConfig = {
|
|
name: args.containerName,
|
|
Image: args.image,
|
|
};
|
|
|
|
// Basic settings
|
|
if (args.command) {
|
|
containerConfig.Cmd = args.command.split(' ');
|
|
}
|
|
if (args.entrypoint) {
|
|
containerConfig.Entrypoint = args.entrypoint.split(' ');
|
|
}
|
|
if (args.workingDir) {
|
|
containerConfig.WorkingDir = args.workingDir;
|
|
}
|
|
|
|
return containerConfig;
|
|
}
|
|
|
|
/**
|
|
* Build environment variables configuration
|
|
* @param {Array} envVars - Environment variables array
|
|
* @returns {Array} - Formatted environment variables
|
|
*/
|
|
export function buildEnvConfig(envVars) {
|
|
if (!envVars || !Array.isArray(envVars)) {
|
|
return [];
|
|
}
|
|
|
|
return envVars
|
|
.filter(e => e.name && e.value !== undefined)
|
|
.map(e => {
|
|
const name = validation.sanitizeEnvVarName(e.name);
|
|
const value = validation.sanitizeEnvVarValue(e.value);
|
|
return name && value !== null ? `${name}=${value}` : null;
|
|
})
|
|
.filter(e => e !== null);
|
|
}
|
|
|
|
/**
|
|
* Build labels configuration
|
|
* @param {Object} labels - Labels object
|
|
* @returns {Object} - Sanitized labels
|
|
*/
|
|
export function buildLabelsConfig(labels) {
|
|
if (!labels || typeof labels !== 'object') {
|
|
return {};
|
|
}
|
|
|
|
const sanitizedLabels = {};
|
|
for (const [key, value] of Object.entries(labels)) {
|
|
const sanitizedKey = validation.sanitizeLabelKey(key);
|
|
const sanitizedValue = validation.sanitizeLabelValue(value);
|
|
if (sanitizedKey && sanitizedValue !== null) {
|
|
sanitizedLabels[sanitizedKey] = sanitizedValue;
|
|
}
|
|
}
|
|
|
|
return sanitizedLabels;
|
|
}
|
|
|
|
/**
|
|
* Build networking configuration
|
|
* @param {Object} args - Deployment arguments
|
|
* @returns {Object} - HostConfig networking settings
|
|
*/
|
|
export function buildNetworkingConfig(args) {
|
|
const hostConfig = {
|
|
NetworkMode: args.networkMode || 'bridge',
|
|
};
|
|
|
|
// Port bindings
|
|
if (args.ports && Array.isArray(args.ports)) {
|
|
hostConfig.PortBindings = {};
|
|
args.ports.forEach((portStr) => {
|
|
const sanitizedPort = validation.sanitizeString(portStr, 50);
|
|
if (validation.isValidPortMapping(sanitizedPort)) {
|
|
if (sanitizedPort.includes(':')) {
|
|
const [hostPort, rest] = sanitizedPort.split(':');
|
|
const [containerPort, protocol] = rest.split('/');
|
|
hostConfig.PortBindings[`${containerPort}/${protocol || 'tcp'}`] = [{ HostPort: hostPort }];
|
|
} else {
|
|
const [containerPort, protocol] = sanitizedPort.split('/');
|
|
hostConfig.PortBindings[`${containerPort}/${protocol || 'tcp'}`] = [{ HostPort: containerPort }];
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// DNS
|
|
if (args.dns && Array.isArray(args.dns)) {
|
|
hostConfig.Dns = args.dns
|
|
.map(dns => validation.sanitizeString(dns, 50))
|
|
.filter(dns => validation.isValidDnsServer(dns));
|
|
}
|
|
|
|
// Extra hosts
|
|
if (args.extraHosts && Array.isArray(args.extraHosts)) {
|
|
hostConfig.ExtraHosts = args.extraHosts
|
|
.map(host => validation.sanitizeString(host, 200))
|
|
.filter(host => host.includes(':'));
|
|
}
|
|
|
|
return hostConfig;
|
|
}
|
|
|
|
/**
|
|
* Build volumes configuration
|
|
* @param {Object} args - Deployment arguments
|
|
* @returns {Object} - HostConfig volumes settings
|
|
*/
|
|
export function buildVolumesConfig(args) {
|
|
const hostConfig = {};
|
|
|
|
// Volumes
|
|
if (args.volumes && Array.isArray(args.volumes)) {
|
|
hostConfig.Binds = args.volumes
|
|
.map(v => validation.sanitizeString(v, 500))
|
|
.filter(v => v && validation.isValidVolumeMount(v));
|
|
}
|
|
|
|
// Tmpfs
|
|
if (args.tmpfs && Array.isArray(args.tmpfs)) {
|
|
hostConfig.Tmpfs = {};
|
|
args.tmpfs.forEach(tmpfsStr => {
|
|
const sanitized = validation.sanitizeString(tmpfsStr, 100);
|
|
const [path, ...opts] = sanitized.split(':');
|
|
if (path) {
|
|
hostConfig.Tmpfs[path] = opts.join(':') || '';
|
|
}
|
|
});
|
|
}
|
|
|
|
return hostConfig;
|
|
}
|
|
|
|
/**
|
|
* Build resources configuration
|
|
* @param {Object} args - Deployment arguments
|
|
* @returns {Object} - HostConfig resources settings
|
|
*/
|
|
export function buildResourcesConfig(args) {
|
|
const hostConfig = {};
|
|
|
|
// CPU limits
|
|
if (args.cpuLimit) {
|
|
hostConfig.NanoCpus = args.cpuLimit * 1000000000; // Convert to nanoseconds
|
|
}
|
|
if (args.cpuReservation) {
|
|
hostConfig.CpuQuota = args.cpuReservation * 1000000000;
|
|
}
|
|
if (args.cpuShares) {
|
|
hostConfig.CpuShares = args.cpuShares;
|
|
}
|
|
|
|
// Memory limits
|
|
if (args.memoryLimit) {
|
|
hostConfig.Memory = args.memoryLimit * 1024 * 1024; // Convert MB to bytes
|
|
}
|
|
if (args.memoryReservation) {
|
|
hostConfig.MemoryReservation = args.memoryReservation * 1024 * 1024;
|
|
}
|
|
if (args.memorySwap !== undefined && args.memorySwap !== null) {
|
|
hostConfig.MemorySwap = args.memorySwap === -1 ? -1 : args.memorySwap * 1024 * 1024;
|
|
}
|
|
|
|
// Devices
|
|
if (args.devices && Array.isArray(args.devices)) {
|
|
hostConfig.Devices = args.devices
|
|
.map(deviceStr => validation.sanitizeString(deviceStr, 200))
|
|
.map(deviceStr => {
|
|
const parts = deviceStr.split(':');
|
|
return {
|
|
PathOnHost: parts[0],
|
|
PathInContainer: parts[1] || parts[0],
|
|
CgroupPermissions: parts[2] || 'rwm'
|
|
};
|
|
});
|
|
}
|
|
|
|
return hostConfig;
|
|
}
|
|
|
|
/**
|
|
* Build security configuration
|
|
* @param {Object} args - Deployment arguments
|
|
* @returns {Object} - HostConfig security settings
|
|
*/
|
|
export function buildSecurityConfig(args) {
|
|
const hostConfig = {};
|
|
|
|
// Privileged
|
|
if (args.privileged === true) {
|
|
hostConfig.Privileged = true;
|
|
}
|
|
|
|
// Capabilities
|
|
if (args.capabilities && Array.isArray(args.capabilities)) {
|
|
hostConfig.CapAdd = args.capabilities
|
|
.map(cap => validation.sanitizeString(cap, 50).toUpperCase())
|
|
.filter(cap => /^[A-Z_]+$/.test(cap));
|
|
}
|
|
|
|
// Security options
|
|
if (args.securityOpts && Array.isArray(args.securityOpts)) {
|
|
hostConfig.SecurityOpt = args.securityOpts
|
|
.map(opt => validation.sanitizeString(opt, 200));
|
|
}
|
|
|
|
return hostConfig;
|
|
}
|
|
|
|
/**
|
|
* Build runtime configuration
|
|
* @param {Object} args - Deployment arguments
|
|
* @returns {Object} - HostConfig runtime settings
|
|
*/
|
|
export function buildRuntimeConfig(args) {
|
|
const hostConfig = {};
|
|
|
|
// Restart policy
|
|
if (args.restartPolicy) {
|
|
hostConfig.RestartPolicy = {
|
|
Name: args.restartPolicy,
|
|
MaximumRetryCount: args.restartMaxRetries || 0
|
|
};
|
|
}
|
|
|
|
// Auto remove
|
|
if (args.autoRemove === true) {
|
|
hostConfig.AutoRemove = true;
|
|
}
|
|
|
|
// Init process
|
|
if (args.init === true) {
|
|
hostConfig.Init = true;
|
|
}
|
|
|
|
// Sysctls
|
|
if (args.sysctls && typeof args.sysctls === 'object') {
|
|
hostConfig.Sysctls = {};
|
|
for (const [key, value] of Object.entries(args.sysctls)) {
|
|
const sanitizedKey = validation.sanitizeString(key, 100);
|
|
const sanitizedValue = validation.sanitizeString(String(value), 100);
|
|
if (sanitizedKey && sanitizedValue) {
|
|
hostConfig.Sysctls[sanitizedKey] = sanitizedValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ulimits
|
|
if (args.ulimits && Array.isArray(args.ulimits)) {
|
|
hostConfig.Ulimits = args.ulimits
|
|
.map(ulimit => {
|
|
if (typeof ulimit === 'object' && ulimit.Name) {
|
|
return {
|
|
Name: validation.sanitizeString(ulimit.Name, 50),
|
|
Soft: validation.validateNumber(ulimit.Soft, 0, Infinity),
|
|
Hard: validation.validateNumber(ulimit.Hard, 0, Infinity)
|
|
};
|
|
}
|
|
return null;
|
|
})
|
|
.filter(ulimit => ulimit !== null);
|
|
}
|
|
|
|
// OOM kill disable
|
|
if (args.oomKillDisable === true) {
|
|
hostConfig.OomKillDisable = true;
|
|
}
|
|
|
|
// PIDs limit
|
|
if (args.pidsLimit !== undefined && args.pidsLimit !== null) {
|
|
hostConfig.PidsLimit = args.pidsLimit === -1 ? 0 : args.pidsLimit;
|
|
}
|
|
|
|
// Shared memory size
|
|
if (args.shmSize) {
|
|
hostConfig.ShmSize = args.shmSize * 1024 * 1024; // Convert MB to bytes
|
|
}
|
|
|
|
return hostConfig;
|
|
}
|
|
|