UNPKG

@limlabs/limo

Version:

Infrastructure as Code generator

238 lines (237 loc) 10.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getResourceGroupType = exports.getFramework = exports.getResourceGroupName = exports.init = exports.initOptionsSchema = void 0; const zod_1 = __importDefault(require("zod")); const commander_1 = require("commander"); const prompts_1 = __importDefault(require("prompts")); const path_1 = __importDefault(require("path")); const frameworks_1 = require("../frameworks"); const resourceGroups_1 = require("../resourceGroups"); const workspace_1 = require("../workspace"); const data_1 = require("../migrations/data"); const process_1 = require("process"); const apply_1 = require("../migrations/apply"); const date_1 = require("../utils/date"); const templates_1 = require("../templates"); const cli_helpers_1 = require("../cli-helpers"); exports.initOptionsSchema = zod_1.default.object({ directory: zod_1.default.string().optional().default(process.cwd()), name: zod_1.default.string().optional(), framework: zod_1.default.string().optional(), resourceGroupType: zod_1.default.enum(resourceGroups_1.AllResourceGroupTypes).optional(), noScroll: zod_1.default.boolean().optional(), apply: zod_1.default.boolean().optional() }); exports.init = new commander_1.Command() .name("init") .allowUnknownOption(true) .description("Initialize a new infrastructure resource group") .option("-d, --directory <directory>", "Directory where the infrastructure folder should be added", process.cwd()) .option("-n, --name <name>", "Name of the resourceGroup") .option("-t, --resourceGroupType <type>", "Type of resource group to create") .option("-f, --framework <framework>", "Framework to use") .option("--noScroll", "Disable scrolling output") .option("--apply", "Apply the generated platform migration") .option("--inputs <otherInputs>", "Resource group / framework specific inputs: comma separated key=value format") .action((options) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; const cmdArgs = exports.initOptionsSchema.parse(options); const other = (0, cli_helpers_1.parseOtherArgs)((_b = (_a = options.inputs) === null || _a === void 0 ? void 0 : _a.split(",")) !== null && _b !== void 0 ? _b : []); if (cmdArgs.directory) { process.chdir(cmdArgs.directory); } let frameworkType = cmdArgs.framework; if (!frameworkType) { frameworkType = yield (0, frameworks_1.detectFramework)(cmdArgs.directory); } frameworkType = frameworkType != "unknown" ? frameworkType : yield getFramework(cmdArgs); yield (0, workspace_1.renderWorkspace)(); const resourceGroupName = yield getResourceGroupName(cmdArgs); const resourceGroupType = yield getResourceGroupType(cmdArgs, frameworkType); const resourceGroup = (0, resourceGroups_1.importResourceGroupType)(resourceGroupType, resourceGroupName, cmdArgs.directory); if (!resourceGroup || !resourceGroup.inputSchema) { throw new Error("Resource group type not found"); } const promptInputs = []; if (frameworkType !== "unknown") { const framework = yield (0, frameworks_1.importFramework)(frameworkType, resourceGroupType, resourceGroupName, cmdArgs.directory); if (!framework) { throw new Error("Framework not found"); } if (framework.inputSchema) { const frameworkInputs = yield (0, templates_1.getInputPrompts)(framework.inputSchema); promptInputs.push(...frameworkInputs); } } const resourceGroupInputs = yield (0, templates_1.getInputPrompts)(resourceGroup.inputSchema); resourceGroupInputs.forEach((resourceGroupInput) => { if (!promptInputs.find((input) => input.name === resourceGroupInput.name)) { promptInputs.push(resourceGroupInput); } }); const answers = {}; const newPrompts = promptInputs.filter((resourceGroup) => { const key = resourceGroup.name; const type = resourceGroup.type; if (other[key]) { switch (type) { case "text": answers[key] = other[key]; break; case "number": answers[key] = parseInt(other[key]); break; case "confirm": answers[key] = other[key] === "true"; break; case "select": if (!resourceGroup.choices || !Array.isArray(resourceGroup.choices)) { throw new Error(`Error choices not found for select type: ${resourceGroup.name}`); } if (resourceGroup.choices.filter((choice) => choice.value === other[key]).length === 0) { throw new Error(`Error choice ${other[key]} not found for select type: ${resourceGroup.name}`); } answers[key] = other[key]; default: break; } return false; } return true; }); const inputs = yield (0, prompts_1.default)(newPrompts); const initID = `init-${resourceGroupName}`.replace(" ", "-"); const initMigration = { id: initID, up: [ { type: "initResourceGroup", options: { args: { name: resourceGroupName, type: resourceGroupType, framework: frameworkType, inputs: Object.assign(Object.assign({}, answers), inputs) } } } ], down: [ { type: "removeResourceGroup", options: { args: { name: resourceGroupName } } } ] }; if (frameworkType !== "unknown") { initMigration.up.push({ type: "configureFramework", options: { args: { frameworkType: frameworkType, resourceGroupType: resourceGroupType, resourceGroupName: resourceGroupName, operation: "apply", inputs: Object.assign(Object.assign({}, answers), inputs) } } }); if (!initMigration.down) { initMigration.down = []; } initMigration.down.push({ type: "configureFramework", options: { args: { frameworkType: frameworkType, resourceGroupType: resourceGroupType, resourceGroupName: resourceGroupName, operation: "revert", inputs: Object.assign(Object.assign({}, answers), inputs) } } }); } yield (0, data_1.ensureMigrations)(); const infrastructurePath = path_1.default.join((0, process_1.cwd)(), "infrastructure"); const migrationPath = path_1.default.join(infrastructurePath, "migrations"); const timestamp = (0, date_1.getCurrentTimestamp)(); yield (0, apply_1.ensureMigrationNotApplied)(initMigration); yield (0, data_1.exportMigration)(initMigration, path_1.default.join(migrationPath, `${timestamp}-${initID}.yaml`)); if (cmdArgs.apply === true) { yield (0, apply_1.triggerMigration)(initMigration, true, { noScroll: cmdArgs.noScroll }); } else { console.log("Migration created but not applied."); } })); function getResourceGroupName(cmdArgs) { return __awaiter(this, void 0, void 0, function* () { if (cmdArgs.name) { return cmdArgs.name; } const answer = yield (0, prompts_1.default)({ type: "text", name: "name", message: "Select a resource group name" }); return answer.name; }); } exports.getResourceGroupName = getResourceGroupName; function getFramework(cmdArgs) { return __awaiter(this, void 0, void 0, function* () { if (cmdArgs.framework) { return cmdArgs.framework; } const answer = yield (0, prompts_1.default)({ type: "select", name: "framework", message: "Select a framework", choices: frameworks_1.AllFrameworkTypes.map((type) => ({ title: type, value: type })) }); return answer.framework; }); } exports.getFramework = getFramework; function getResourceGroupType(cmdArgs, frameworkType) { return __awaiter(this, void 0, void 0, function* () { if (cmdArgs.resourceGroupType) { return cmdArgs.resourceGroupType; } const supportedResourceGroupTypes = frameworkType === "unknown" ? resourceGroups_1.AllResourceGroupTypes : yield (0, frameworks_1.getSupportedResourceGroupTypesForFramework)(frameworkType); const answer = yield (0, prompts_1.default)({ type: "select", name: "resourceGroupType", message: "Select a resource group type", choices: supportedResourceGroupTypes.map((type) => ({ title: type, value: type })) }); return answer.resourceGroupType; }); } exports.getResourceGroupType = getResourceGroupType;