276 lines
6.9 KiB
TypeScript
276 lines
6.9 KiB
TypeScript
/**
|
|
* CLI Interface for isocreator
|
|
*/
|
|
|
|
import { log } from './logging.ts';
|
|
import { IsoBuilder } from './classes/iso-builder.ts';
|
|
import { IsoCache } from './classes/iso-cache.ts';
|
|
import { ConfigManager } from './classes/config-manager.ts';
|
|
|
|
/**
|
|
* Display help information
|
|
*/
|
|
function showHelp() {
|
|
console.log(`
|
|
isocreator - Ubuntu ISO Customization Tool
|
|
|
|
USAGE:
|
|
isocreator <COMMAND> [OPTIONS]
|
|
|
|
COMMANDS:
|
|
build Build a customized ISO
|
|
cache Manage ISO cache
|
|
template Generate config template
|
|
validate Validate config file
|
|
version Show version information
|
|
help Show this help message
|
|
|
|
BUILD OPTIONS:
|
|
--config <file> Use a YAML config file
|
|
--ubuntu-version <version> Ubuntu version (22.04, 24.04, etc.)
|
|
--arch <arch> Architecture (amd64 or arm64)
|
|
--wifi-ssid <ssid> WiFi SSID
|
|
--wifi-password <password> WiFi password
|
|
--hostname <name> System hostname
|
|
--output <path> Output ISO path
|
|
--ssh-key <path> Path to SSH public key
|
|
|
|
CACHE OPTIONS:
|
|
cache list List cached ISOs
|
|
cache download <version> Download and cache an ISO
|
|
cache clean Clean all cached ISOs
|
|
|
|
TEMPLATE OPTIONS:
|
|
template create Generate config template to stdout
|
|
template create --output <file> Save template to file
|
|
|
|
VALIDATE OPTIONS:
|
|
validate <file> Validate a config file
|
|
|
|
EXAMPLES:
|
|
# Build from config file
|
|
isocreator build --config myconfig.yaml
|
|
|
|
# Quick build with CLI flags
|
|
isocreator build \\
|
|
--ubuntu-version 24.04 \\
|
|
--arch amd64 \\
|
|
--wifi-ssid "MyWiFi" \\
|
|
--wifi-password "secret123" \\
|
|
--hostname "myserver" \\
|
|
--output ./custom-ubuntu.iso
|
|
|
|
# Generate config template
|
|
isocreator template create --output config.yaml
|
|
|
|
# List cached ISOs
|
|
isocreator cache list
|
|
|
|
SYSTEM REQUIREMENTS:
|
|
- xorriso (for ISO manipulation)
|
|
- syslinux-utils (for USB-bootable ISOs)
|
|
|
|
Install on Ubuntu/Debian:
|
|
sudo apt install xorriso syslinux-utils
|
|
|
|
Install on macOS:
|
|
brew install xorriso syslinux
|
|
|
|
For more information, visit:
|
|
https://code.foss.global/serve.zone/isocreator
|
|
`);
|
|
}
|
|
|
|
/**
|
|
* Show version information
|
|
*/
|
|
function showVersion() {
|
|
console.log('isocreator version 1.0.0');
|
|
console.log('Ubuntu ISO customization tool');
|
|
console.log('https://code.foss.global/serve.zone/isocreator');
|
|
}
|
|
|
|
/**
|
|
* Parse CLI arguments
|
|
*/
|
|
function parseArgs(args: string[]): Map<string, string | boolean> {
|
|
const parsed = new Map<string, string | boolean>();
|
|
let i = 0;
|
|
|
|
while (i < args.length) {
|
|
const arg = args[i];
|
|
|
|
if (arg.startsWith('--')) {
|
|
const key = arg.substring(2);
|
|
const nextArg = args[i + 1];
|
|
|
|
if (nextArg && !nextArg.startsWith('--')) {
|
|
parsed.set(key, nextArg);
|
|
i += 2;
|
|
} else {
|
|
parsed.set(key, true);
|
|
i += 1;
|
|
}
|
|
} else {
|
|
parsed.set(`_arg${i}`, arg);
|
|
i += 1;
|
|
}
|
|
}
|
|
|
|
return parsed;
|
|
}
|
|
|
|
/**
|
|
* Handle build command
|
|
*/
|
|
async function handleBuild(args: Map<string, string | boolean>) {
|
|
const builder = new IsoBuilder();
|
|
const configManager = new ConfigManager();
|
|
|
|
// Check if config file is provided
|
|
if (args.has('config')) {
|
|
const configPath = args.get('config') as string;
|
|
const config = await configManager.loadFromFile(configPath);
|
|
|
|
await builder.build(config, (step, progress) => {
|
|
console.log(`[${progress}%] ${step}`);
|
|
});
|
|
} else {
|
|
// Build from CLI flags
|
|
log.error('CLI flag mode not yet implemented. Please use --config for now.');
|
|
log.info('Generate a template: isocreator template create --output config.yaml');
|
|
Deno.exit(1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle cache commands
|
|
*/
|
|
async function handleCache(args: Map<string, string | boolean>) {
|
|
const cache = new IsoCache();
|
|
const subcommand = args.get('_arg1') as string;
|
|
|
|
if (!subcommand || subcommand === 'list') {
|
|
const entries = await cache.list();
|
|
|
|
if (entries.length === 0) {
|
|
console.log('No cached ISOs found.');
|
|
return;
|
|
}
|
|
|
|
console.log('\nCached ISOs:');
|
|
console.log('━'.repeat(80));
|
|
|
|
for (const entry of entries) {
|
|
const sizeMB = (entry.size / 1024 / 1024).toFixed(2);
|
|
const date = new Date(entry.downloadedAt).toLocaleDateString();
|
|
console.log(`${entry.version} (${entry.architecture}) - ${sizeMB} MB - ${date}`);
|
|
console.log(` ${entry.path}`);
|
|
}
|
|
|
|
console.log('━'.repeat(80));
|
|
} else if (subcommand === 'clean') {
|
|
await cache.clean();
|
|
console.log('Cache cleaned.');
|
|
} else if (subcommand === 'download') {
|
|
const version = args.get('_arg2') as string;
|
|
const arch = (args.get('arch') as string) || 'amd64';
|
|
|
|
if (!version) {
|
|
log.error('Please specify a version: isocreator cache download <version>');
|
|
Deno.exit(1);
|
|
}
|
|
|
|
await cache.downloadAndCache(version, arch as 'amd64' | 'arm64', (downloaded, total) => {
|
|
const percent = ((downloaded / total) * 100).toFixed(1);
|
|
process.stdout.write(`\r📥 Download progress: ${percent}%`);
|
|
});
|
|
|
|
console.log();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle template commands
|
|
*/
|
|
async function handleTemplate(args: Map<string, string | boolean>) {
|
|
const configManager = new ConfigManager();
|
|
const subcommand = args.get('_arg1') as string;
|
|
|
|
if (!subcommand || subcommand === 'create') {
|
|
const outputPath = args.get('output') as string | undefined;
|
|
|
|
if (outputPath) {
|
|
await configManager.saveTemplate(outputPath);
|
|
} else {
|
|
console.log(configManager.generateTemplate());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle validate command
|
|
*/
|
|
async function handleValidate(args: Map<string, string | boolean>) {
|
|
const configPath = args.get('_arg1') as string;
|
|
|
|
if (!configPath) {
|
|
log.error('Please specify a config file: isocreator validate <file>');
|
|
Deno.exit(1);
|
|
}
|
|
|
|
const configManager = new ConfigManager();
|
|
try {
|
|
await configManager.loadFromFile(configPath);
|
|
log.success('Configuration is valid!');
|
|
} catch (err) {
|
|
log.error(`Validation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
Deno.exit(1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main CLI entry point
|
|
*/
|
|
export async function startCli() {
|
|
const args = parseArgs(Deno.args);
|
|
const command = args.get('_arg0') as string;
|
|
|
|
try {
|
|
switch (command) {
|
|
case 'build':
|
|
await handleBuild(args);
|
|
break;
|
|
|
|
case 'cache':
|
|
await handleCache(args);
|
|
break;
|
|
|
|
case 'template':
|
|
await handleTemplate(args);
|
|
break;
|
|
|
|
case 'validate':
|
|
await handleValidate(args);
|
|
break;
|
|
|
|
case 'version':
|
|
showVersion();
|
|
break;
|
|
|
|
case 'help':
|
|
case undefined:
|
|
showHelp();
|
|
break;
|
|
|
|
default:
|
|
log.error(`Unknown command: ${command}`);
|
|
log.info('Run "isocreator help" for usage information');
|
|
Deno.exit(1);
|
|
}
|
|
} catch (err) {
|
|
log.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
Deno.exit(1);
|
|
}
|
|
}
|