@deploystack/docker-to-iac
Version:
Translate docker run and docker compose file to Infrastructure as Code
152 lines (151 loc) • 6.66 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseEnvFile = void 0;
exports.translate = translate;
exports.getParserInfo = getParserInfo;
exports.listAllParsers = listAllParsers;
exports.listServices = listServices;
exports.clearStoredEnvVars = clearStoredEnvVars;
const base_parser_1 = require("./parsers/base-parser");
const aws_cloudformation_1 = __importDefault(require("./parsers/aws-cloudformation"));
const render_1 = __importDefault(require("./parsers/render"));
const digitalocean_1 = __importDefault(require("./parsers/digitalocean"));
const helm_1 = __importDefault(require("./parsers/helm"));
const factory_1 = require("./sources/factory");
const parseEnvFile_1 = require("./utils/parseEnvFile");
Object.defineProperty(exports, "parseEnvFile", { enumerable: true, get: function () { return parseEnvFile_1.parseEnvFile; } });
const resolveServiceConnections_1 = require("./utils/resolveServiceConnections");
const detectDatabaseEnvVars_1 = require("./utils/detectDatabaseEnvVars");
// Store for generated environment variables
const generatedEnvVars = new Map();
const parsers = [
aws_cloudformation_1.default,
render_1.default,
digitalocean_1.default,
helm_1.default,
];
function getOrCreateEnvVars(serviceName, imageConfig, envGeneration, persistenceKey) {
if (!persistenceKey) {
return {};
}
// Get or initialize service-level storage
if (!generatedEnvVars.has(persistenceKey)) {
generatedEnvVars.set(persistenceKey, {});
}
const keyStore = generatedEnvVars.get(persistenceKey);
// Return existing variables if already generated
if (keyStore[serviceName]) {
return keyStore[serviceName];
}
// Store will be populated by the source parser
keyStore[serviceName] = {};
return keyStore[serviceName];
}
function getProcessedConfig(content, sourceType, options) {
const sourceParser = (0, factory_1.createSourceParser)(sourceType);
if (!sourceParser.validate(content)) {
throw new Error(`Invalid ${sourceType} content`);
}
// Inject the environment variable getter
const envVarGetter = (serviceName, imageConfig) => getOrCreateEnvVars(serviceName, imageConfig, options.envGeneration, options.persistenceKey);
// Parse with environment variable persistence
return sourceParser.parse(content, {
environmentGeneration: options.envGeneration,
environmentVariables: options.envVariables,
getPersistedEnvVars: envVarGetter,
setPersistedEnvVars: (serviceName, vars) => {
if (options.persistenceKey) {
const keyStore = generatedEnvVars.get(options.persistenceKey);
keyStore[serviceName] = vars;
}
}
});
}
function translate(content, options) {
try {
const parser = parsers.find(p => p.getInfo().languageAbbreviation.toLowerCase() === options.target.toLowerCase());
if (!parser) {
throw new Error(`Unsupported target language: ${options.target}`);
}
const containerConfig = getProcessedConfig(content, options.source, {
envGeneration: options.environmentVariableGeneration,
envVariables: options.environmentVariables,
persistenceKey: options.persistenceKey
});
// Process service connections if provided
let resolvedServiceConnections;
if (options.serviceConnections && options.serviceConnections.mappings.length > 0) {
// Use the simplified service connection resolver - no provider-specific transformations
resolvedServiceConnections = (0, resolveServiceConnections_1.resolveServiceConnections)(containerConfig, options.serviceConnections);
// Add service connections to the container config for parsers to use
containerConfig.serviceConnections = resolvedServiceConnections;
}
else if (options.target.toLowerCase() !== 'cfn') {
// Auto-detect database connections if not AWS CloudFormation
// (CloudFormation doesn't support direct service-to-service references)
const autoDetectedMappings = (0, detectDatabaseEnvVars_1.generateDatabaseServiceConnections)(containerConfig);
if (autoDetectedMappings.length > 0) {
// Process auto-detected connections
resolvedServiceConnections = (0, resolveServiceConnections_1.resolveServiceConnections)(containerConfig, { mappings: autoDetectedMappings });
// Add to container config
containerConfig.serviceConnections = resolvedServiceConnections;
}
}
// Get files from parser
const filesOutput = parser.parseFiles(containerConfig);
const result = {
files: {},
serviceConnections: resolvedServiceConnections
};
// Process each file to ensure correct formatting
for (const [path, fileData] of Object.entries(filesOutput)) {
result.files[path] = {
content: typeof fileData.content === 'string'
? fileData.content
: (0, base_parser_1.formatResponse)(JSON.stringify(fileData.content, null, 2), fileData.format),
format: fileData.format,
isMain: fileData.isMain
};
}
return result;
}
catch (e) {
console.error(`Error translating content: ${e}`);
throw e;
}
}
function listServices(content, options) {
try {
const config = getProcessedConfig(content, options.source, {
envGeneration: options.environmentVariableGeneration,
envVariables: options.environmentVariables,
persistenceKey: options.persistenceKey
});
return config.services;
}
catch (e) {
console.error(`Error listing services: ${e}`);
throw e;
}
}
function clearStoredEnvVars(persistenceKey) {
if (persistenceKey) {
generatedEnvVars.delete(persistenceKey);
}
else {
generatedEnvVars.clear();
}
}
function getParserInfo(languageAbbreviation) {
const parser = parsers.find(parser => parser.getInfo().languageAbbreviation.toLowerCase() === languageAbbreviation.toLowerCase());
if (!parser) {
throw new Error(`Unsupported target language: ${languageAbbreviation}`);
}
return parser.getInfo();
}
function listAllParsers() {
return parsers.map(parser => parser.getInfo());
}