feat(cli): Add initial MOXYTOOL implementation, packaging, install/uninstall scripts, CI and release workflows
This commit is contained in:
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/moxytool',
|
||||
version: '1.1.0',
|
||||
description: 'Proxmox administration tool for vGPU setup, VM management, and cluster configuration'
|
||||
}
|
||||
28
ts/index.ts
Normal file
28
ts/index.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* MOXYTOOL - Proxmox Administration Tool
|
||||
* Node.js entry point for library usage
|
||||
*/
|
||||
|
||||
import * as cli from './moxytool.cli.ts';
|
||||
import { logger } from './moxytool.logging.ts';
|
||||
import process from 'node:process';
|
||||
|
||||
/**
|
||||
* Main entry point for MOXYTOOL
|
||||
* Initializes the CLI and executes the given command
|
||||
*/
|
||||
async function main() {
|
||||
await cli.runCli();
|
||||
}
|
||||
|
||||
// Run the main function and handle any errors
|
||||
main().catch((error) => {
|
||||
logger.error(`Error: ${error}`);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// Export for library usage
|
||||
export { logger };
|
||||
export * from './moxytool.cli.ts';
|
||||
112
ts/moxytool.cli.ts
Normal file
112
ts/moxytool.cli.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import * as plugins from './moxytool.plugins.ts';
|
||||
import * as paths from './moxytool.paths.ts';
|
||||
import { logger } from './moxytool.logging.ts';
|
||||
|
||||
export const runCli = async () => {
|
||||
const smartshellInstance = new plugins.smartshell.Smartshell({
|
||||
executor: 'bash',
|
||||
});
|
||||
|
||||
const smartcliInstance = new plugins.smartcli.Smartcli();
|
||||
|
||||
// Standard command (no arguments)
|
||||
smartcliInstance.standardCommand().subscribe(async () => {
|
||||
logger.log('info', 'MOXYTOOL - Proxmox Administration Tool');
|
||||
logger.log('info', '');
|
||||
logger.log('info', 'Available commands:');
|
||||
logger.log('info', '* vgpu-setup - Install and configure Proxmox vGPU support');
|
||||
logger.log('info', '');
|
||||
logger.log('info', 'Usage: moxytool <command> [options]');
|
||||
});
|
||||
|
||||
// vGPU setup command
|
||||
smartcliInstance.addCommand('vgpu-setup').subscribe(async (argvArg) => {
|
||||
logger.log('ok', 'Starting Proxmox vGPU setup process');
|
||||
logger.log('info', 'This will install vGPU support for NVIDIA GPUs on Proxmox');
|
||||
logger.log('info', '');
|
||||
|
||||
// Check for arguments
|
||||
const step = argvArg.step;
|
||||
const url = argvArg.url;
|
||||
const file = argvArg.file;
|
||||
const debug = argvArg.debug;
|
||||
|
||||
// Check if running on Proxmox
|
||||
try {
|
||||
const result = await smartshellInstance.exec('which pveversion');
|
||||
if (result.exitCode !== 0) {
|
||||
logger.log('error', 'This system does not appear to be running Proxmox');
|
||||
logger.log('error', 'Please run this command on a Proxmox host');
|
||||
Deno.exit(1);
|
||||
}
|
||||
} catch (e) {
|
||||
logger.log('error', 'Failed to verify Proxmox installation');
|
||||
logger.log('error', 'Please ensure you are running this on a Proxmox host');
|
||||
Deno.exit(1);
|
||||
}
|
||||
|
||||
// Create temporary directory
|
||||
const tmpDir = '/tmp/moxytool-vgpu-setup';
|
||||
await smartshellInstance.exec(`mkdir -p ${tmpDir}`);
|
||||
|
||||
try {
|
||||
// Step 1: Clone and run the installer script
|
||||
logger.log('info', 'Step 1: Downloading Proxmox vGPU installer (supports v9)...');
|
||||
const cloneResult = await smartshellInstance.exec(
|
||||
`cd ${tmpDir} && git clone https://github.com/anomixer/proxmox-vgpu-installer.git`,
|
||||
);
|
||||
|
||||
if (cloneResult.exitCode !== 0) {
|
||||
logger.log('error', 'Failed to clone the installer repository');
|
||||
logger.log('error', cloneResult.stderr || 'Unknown error');
|
||||
Deno.exit(1);
|
||||
}
|
||||
|
||||
logger.log('ok', 'Installer downloaded successfully');
|
||||
logger.log('info', '');
|
||||
|
||||
// Build command with arguments
|
||||
let command = 'bash proxmox-installer.sh';
|
||||
if (step) {
|
||||
command += ` --step ${step}`;
|
||||
}
|
||||
if (url) {
|
||||
command += ` --url ${url}`;
|
||||
}
|
||||
if (file) {
|
||||
command += ` --file ${file}`;
|
||||
}
|
||||
if (debug) {
|
||||
command += ' --debug';
|
||||
}
|
||||
|
||||
logger.log('info', 'Running installer script...');
|
||||
logger.log('info', 'Please follow the interactive prompts');
|
||||
logger.log('info', '');
|
||||
|
||||
// Run the installer script interactively
|
||||
const installResult = await smartshellInstance.exec(
|
||||
`cd ${tmpDir}/proxmox-vgpu-installer && ${command}`,
|
||||
);
|
||||
|
||||
if (installResult.exitCode !== 0) {
|
||||
logger.log('error', 'Installer script failed');
|
||||
logger.log('error', installResult.stderr || 'Unknown error');
|
||||
Deno.exit(1);
|
||||
}
|
||||
|
||||
logger.log('ok', 'vGPU setup process completed');
|
||||
logger.log('info', '');
|
||||
logger.log('info', 'Next steps:');
|
||||
logger.log('info', '1. If prompted, reboot your system');
|
||||
logger.log('info', '2. After reboot, run this command again to continue setup');
|
||||
logger.log('info', '3. Verify installation with: mdevctl types');
|
||||
logger.log('info', '4. Configure your VMs with vGPU in the Proxmox web UI');
|
||||
} catch (error) {
|
||||
logger.log('error', `Setup failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
Deno.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
smartcliInstance.startParse();
|
||||
};
|
||||
57
ts/moxytool.logging.ts
Normal file
57
ts/moxytool.logging.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import * as plugins from './moxytool.plugins.ts';
|
||||
|
||||
/**
|
||||
* A simple logger class for MOXYTOOL
|
||||
*/
|
||||
class Logger {
|
||||
private static instance: Logger;
|
||||
|
||||
public static getInstance(): Logger {
|
||||
if (!Logger.instance) {
|
||||
Logger.instance = new Logger();
|
||||
}
|
||||
return Logger.instance;
|
||||
}
|
||||
|
||||
public log(level: string, message: string): void {
|
||||
const timestamp = new Date().toISOString();
|
||||
|
||||
switch (level) {
|
||||
case 'error':
|
||||
console.error(`[${timestamp}] [ERROR] ${message}`);
|
||||
break;
|
||||
case 'warn':
|
||||
console.warn(`[${timestamp}] [WARN] ${message}`);
|
||||
break;
|
||||
case 'ok':
|
||||
case 'success':
|
||||
console.log(`[${timestamp}] [OK] ${message}`);
|
||||
break;
|
||||
case 'info':
|
||||
default:
|
||||
console.log(`[${timestamp}] [INFO] ${message}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public error(message: string): void {
|
||||
this.log('error', message);
|
||||
}
|
||||
|
||||
public warn(message: string): void {
|
||||
this.log('warn', message);
|
||||
}
|
||||
|
||||
public info(message: string): void {
|
||||
this.log('info', message);
|
||||
}
|
||||
|
||||
public success(message: string): void {
|
||||
this.log('success', message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logger instance for MOXYTOOL
|
||||
*/
|
||||
export const logger = Logger.getInstance();
|
||||
21
ts/moxytool.paths.ts
Normal file
21
ts/moxytool.paths.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as plugins from './moxytool.plugins.ts';
|
||||
|
||||
/**
|
||||
* Package directory path
|
||||
*/
|
||||
export const packageDir = plugins.path.dirname(plugins.path.dirname(import.meta.url));
|
||||
|
||||
/**
|
||||
* Data directory for moxytool configurations
|
||||
*/
|
||||
export const dataDir = '/etc/moxytool';
|
||||
|
||||
/**
|
||||
* Log directory
|
||||
*/
|
||||
export const logDir = plugins.path.join(dataDir, 'logs');
|
||||
|
||||
/**
|
||||
* Temporary working directory
|
||||
*/
|
||||
export const tmpDir = plugins.path.join(dataDir, 'tmp');
|
||||
29
ts/moxytool.plugins.ts
Normal file
29
ts/moxytool.plugins.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// std library scope
|
||||
import * as path from '@std/path';
|
||||
|
||||
export { path };
|
||||
|
||||
// @pushrocks scope
|
||||
import * as npmextra from '@push.rocks/npmextra';
|
||||
import * as projectinfo from '@push.rocks/projectinfo';
|
||||
import * as smartcli from '@push.rocks/smartcli';
|
||||
import * as smartdelay from '@push.rocks/smartdelay';
|
||||
import * as smartfile from '@push.rocks/smartfile';
|
||||
import * as smartjson from '@push.rocks/smartjson';
|
||||
import * as smartlog from '@push.rocks/smartlog';
|
||||
import * as smartlogDestinationLocal from '@push.rocks/smartlog-destination-local';
|
||||
import * as smartpath from '@push.rocks/smartpath';
|
||||
import * as smartshell from '@push.rocks/smartshell';
|
||||
|
||||
export {
|
||||
npmextra,
|
||||
projectinfo,
|
||||
smartcli,
|
||||
smartdelay,
|
||||
smartfile,
|
||||
smartjson,
|
||||
smartlog,
|
||||
smartlogDestinationLocal,
|
||||
smartpath,
|
||||
smartshell,
|
||||
};
|
||||
Reference in New Issue
Block a user