424 lines
14 KiB
TypeScript
424 lines
14 KiB
TypeScript
import * as plugins from './mod.plugins.js';
|
|
import * as helpers from './helpers.js';
|
|
import { ServiceConfiguration } from './classes.serviceconfiguration.js';
|
|
import { DockerContainer } from './classes.dockercontainer.js';
|
|
import { logger } from '../gitzone.logging.js';
|
|
|
|
export class ServiceManager {
|
|
private config: ServiceConfiguration;
|
|
private docker: DockerContainer;
|
|
|
|
constructor() {
|
|
this.config = new ServiceConfiguration();
|
|
this.docker = new DockerContainer();
|
|
}
|
|
|
|
/**
|
|
* Initialize the service manager
|
|
*/
|
|
public async init(): Promise<void> {
|
|
// Check Docker availability
|
|
if (!(await this.docker.checkDocker())) {
|
|
logger.log('error', 'Error: Docker is not installed. Please install Docker first.');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Load or create configuration
|
|
await this.config.loadOrCreate();
|
|
logger.log('info', `📋 Project: ${this.config.getConfig().PROJECT_NAME}`);
|
|
}
|
|
|
|
/**
|
|
* Start MongoDB service
|
|
*/
|
|
public async startMongoDB(): Promise<void> {
|
|
logger.log('note', '📦 MongoDB:');
|
|
|
|
const config = this.config.getConfig();
|
|
const containers = this.config.getContainerNames();
|
|
const directories = this.config.getDataDirectories();
|
|
|
|
// Ensure data directory exists
|
|
await plugins.smartfile.fs.ensureDir(directories.mongo);
|
|
|
|
const status = await this.docker.getStatus(containers.mongo);
|
|
|
|
switch (status) {
|
|
case 'running':
|
|
logger.log('ok', ' Already running ✓');
|
|
break;
|
|
|
|
case 'stopped':
|
|
if (await this.docker.start(containers.mongo)) {
|
|
logger.log('ok', ' Started ✓');
|
|
} else {
|
|
logger.log('error', ' Failed to start');
|
|
}
|
|
break;
|
|
|
|
case 'not_exists':
|
|
logger.log('note', ' Creating container...');
|
|
|
|
const success = await this.docker.run({
|
|
name: containers.mongo,
|
|
image: 'mongo:7.0',
|
|
ports: {
|
|
[`0.0.0.0:${config.MONGODB_PORT}`]: '27017'
|
|
},
|
|
volumes: {
|
|
[directories.mongo]: '/data/db'
|
|
},
|
|
environment: {
|
|
MONGO_INITDB_ROOT_USERNAME: config.MONGODB_USER,
|
|
MONGO_INITDB_ROOT_PASSWORD: config.MONGODB_PASS,
|
|
MONGO_INITDB_DATABASE: config.MONGODB_NAME
|
|
},
|
|
restart: 'unless-stopped'
|
|
});
|
|
|
|
if (success) {
|
|
logger.log('ok', ' Created and started ✓');
|
|
} else {
|
|
logger.log('error', ' Failed to create container');
|
|
}
|
|
break;
|
|
}
|
|
|
|
logger.log('info', ` Container: ${containers.mongo}`);
|
|
logger.log('info', ` Port: ${config.MONGODB_PORT}`);
|
|
logger.log('info', ` Connection: ${this.config.getMongoConnectionString()}`);
|
|
|
|
// Show Compass connection string
|
|
const networkIp = await helpers.getLocalNetworkIp();
|
|
const compassString = `mongodb://${config.MONGODB_USER}:${config.MONGODB_PASS}@${networkIp}:${config.MONGODB_PORT}/${config.MONGODB_NAME}?authSource=admin`;
|
|
logger.log('ok', ` Compass: ${compassString}`);
|
|
}
|
|
|
|
/**
|
|
* Start MinIO service
|
|
*/
|
|
public async startMinIO(): Promise<void> {
|
|
logger.log('note', '📦 S3/MinIO:');
|
|
|
|
const config = this.config.getConfig();
|
|
const containers = this.config.getContainerNames();
|
|
const directories = this.config.getDataDirectories();
|
|
|
|
// Ensure data directory exists
|
|
await plugins.smartfile.fs.ensureDir(directories.minio);
|
|
|
|
const status = await this.docker.getStatus(containers.minio);
|
|
|
|
switch (status) {
|
|
case 'running':
|
|
logger.log('ok', ' Already running ✓');
|
|
break;
|
|
|
|
case 'stopped':
|
|
if (await this.docker.start(containers.minio)) {
|
|
logger.log('ok', ' Started ✓');
|
|
} else {
|
|
logger.log('error', ' Failed to start');
|
|
}
|
|
break;
|
|
|
|
case 'not_exists':
|
|
logger.log('note', ' Creating container...');
|
|
|
|
const success = await this.docker.run({
|
|
name: containers.minio,
|
|
image: 'minio/minio',
|
|
ports: {
|
|
[config.S3_PORT]: '9000',
|
|
[config.S3_CONSOLE_PORT]: '9001'
|
|
},
|
|
volumes: {
|
|
[directories.minio]: '/data'
|
|
},
|
|
environment: {
|
|
MINIO_ROOT_USER: config.S3_USER,
|
|
MINIO_ROOT_PASSWORD: config.S3_PASS
|
|
},
|
|
restart: 'unless-stopped',
|
|
command: 'server /data --console-address ":9001"'
|
|
});
|
|
|
|
if (success) {
|
|
logger.log('ok', ' Created and started ✓');
|
|
|
|
// Wait for MinIO to be ready
|
|
await plugins.smartdelay.delayFor(3000);
|
|
|
|
// Create default bucket
|
|
await this.docker.exec(
|
|
containers.minio,
|
|
`mc alias set local http://localhost:9000 ${config.S3_USER} ${config.S3_PASS}`
|
|
);
|
|
|
|
await this.docker.exec(
|
|
containers.minio,
|
|
`mc mb local/${config.S3_BUCKET}`
|
|
);
|
|
|
|
logger.log('ok', ` Bucket '${config.S3_BUCKET}' created ✓`);
|
|
} else {
|
|
logger.log('error', ' Failed to create container');
|
|
}
|
|
break;
|
|
}
|
|
|
|
logger.log('info', ` Container: ${containers.minio}`);
|
|
logger.log('info', ` Port: ${config.S3_PORT}`);
|
|
logger.log('info', ` Bucket: ${config.S3_BUCKET}`);
|
|
logger.log('info', ` API: http://${config.S3_HOST}:${config.S3_PORT}`);
|
|
logger.log('info', ` Console: http://${config.S3_HOST}:${config.S3_CONSOLE_PORT} (login: ${config.S3_USER}/***)`);
|
|
}
|
|
|
|
/**
|
|
* Stop MongoDB service
|
|
*/
|
|
public async stopMongoDB(): Promise<void> {
|
|
logger.log('note', '📦 MongoDB:');
|
|
|
|
const containers = this.config.getContainerNames();
|
|
const status = await this.docker.getStatus(containers.mongo);
|
|
|
|
if (status === 'running') {
|
|
if (await this.docker.stop(containers.mongo)) {
|
|
logger.log('ok', ' Stopped ✓');
|
|
} else {
|
|
logger.log('error', ' Failed to stop');
|
|
}
|
|
} else {
|
|
logger.log('note', ' Not running');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stop MinIO service
|
|
*/
|
|
public async stopMinIO(): Promise<void> {
|
|
logger.log('note', '📦 S3/MinIO:');
|
|
|
|
const containers = this.config.getContainerNames();
|
|
const status = await this.docker.getStatus(containers.minio);
|
|
|
|
if (status === 'running') {
|
|
if (await this.docker.stop(containers.minio)) {
|
|
logger.log('ok', ' Stopped ✓');
|
|
} else {
|
|
logger.log('error', ' Failed to stop');
|
|
}
|
|
} else {
|
|
logger.log('note', ' Not running');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Show service status
|
|
*/
|
|
public async showStatus(): Promise<void> {
|
|
helpers.printHeader('Service Status');
|
|
|
|
const config = this.config.getConfig();
|
|
const containers = this.config.getContainerNames();
|
|
|
|
logger.log('info', `Project: ${config.PROJECT_NAME}`);
|
|
console.log();
|
|
|
|
// MongoDB status
|
|
const mongoStatus = await this.docker.getStatus(containers.mongo);
|
|
switch (mongoStatus) {
|
|
case 'running':
|
|
logger.log('ok', '📦 MongoDB: 🟢 Running');
|
|
logger.log('info', ` ├─ Container: ${containers.mongo}`);
|
|
logger.log('info', ` ├─ Connection: ${this.config.getMongoConnectionString()}`);
|
|
|
|
// Show Compass connection string
|
|
const networkIp = await helpers.getLocalNetworkIp();
|
|
const compassString = `mongodb://${config.MONGODB_USER}:${config.MONGODB_PASS}@${networkIp}:${config.MONGODB_PORT}/${config.MONGODB_NAME}?authSource=admin`;
|
|
logger.log('ok', ` └─ Compass: ${compassString}`);
|
|
break;
|
|
case 'stopped':
|
|
logger.log('note', '📦 MongoDB: 🟡 Stopped');
|
|
logger.log('info', ` └─ Container: ${containers.mongo}`);
|
|
break;
|
|
case 'not_exists':
|
|
logger.log('info', '📦 MongoDB: ⚪ Not installed');
|
|
break;
|
|
}
|
|
|
|
// MinIO status
|
|
const minioStatus = await this.docker.getStatus(containers.minio);
|
|
switch (minioStatus) {
|
|
case 'running':
|
|
logger.log('ok', '📦 S3/MinIO: 🟢 Running');
|
|
logger.log('info', ` ├─ Container: ${containers.minio}`);
|
|
logger.log('info', ` ├─ API: http://${config.S3_HOST}:${config.S3_PORT}`);
|
|
logger.log('info', ` ├─ Console: http://${config.S3_HOST}:${config.S3_CONSOLE_PORT}`);
|
|
logger.log('info', ` └─ Bucket: ${config.S3_BUCKET}`);
|
|
break;
|
|
case 'stopped':
|
|
logger.log('note', '📦 S3/MinIO: 🟡 Stopped');
|
|
logger.log('info', ` └─ Container: ${containers.minio}`);
|
|
break;
|
|
case 'not_exists':
|
|
logger.log('info', '📦 S3/MinIO: ⚪ Not installed');
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Show configuration
|
|
*/
|
|
public async showConfig(): Promise<void> {
|
|
helpers.printHeader('Current Configuration');
|
|
|
|
const config = this.config.getConfig();
|
|
|
|
logger.log('info', `Project: ${config.PROJECT_NAME}`);
|
|
console.log();
|
|
|
|
logger.log('note', 'MongoDB:');
|
|
logger.log('info', ` Host: ${config.MONGODB_HOST}:${config.MONGODB_PORT}`);
|
|
logger.log('info', ` Database: ${config.MONGODB_NAME}`);
|
|
logger.log('info', ` User: ${config.MONGODB_USER}`);
|
|
logger.log('info', ' Password: ***');
|
|
logger.log('info', ` Container: ${this.config.getContainerNames().mongo}`);
|
|
logger.log('info', ` Data: ${this.config.getDataDirectories().mongo}`);
|
|
logger.log('info', ` Connection: ${this.config.getMongoConnectionString()}`);
|
|
|
|
console.log();
|
|
logger.log('note', 'S3/MinIO:');
|
|
logger.log('info', ` Host: ${config.S3_HOST}`);
|
|
logger.log('info', ` API Port: ${config.S3_PORT}`);
|
|
logger.log('info', ` Console Port: ${config.S3_CONSOLE_PORT}`);
|
|
logger.log('info', ` User: ${config.S3_USER}`);
|
|
logger.log('info', ' Password: ***');
|
|
logger.log('info', ` Bucket: ${config.S3_BUCKET}`);
|
|
logger.log('info', ` Container: ${this.config.getContainerNames().minio}`);
|
|
logger.log('info', ` Data: ${this.config.getDataDirectories().minio}`);
|
|
logger.log('info', ` API URL: http://${config.S3_HOST}:${config.S3_PORT}`);
|
|
logger.log('info', ` Console URL: http://${config.S3_HOST}:${config.S3_CONSOLE_PORT}`);
|
|
}
|
|
|
|
/**
|
|
* Show MongoDB Compass connection string
|
|
*/
|
|
public async showCompassConnection(): Promise<void> {
|
|
helpers.printHeader('MongoDB Compass Connection');
|
|
|
|
const config = this.config.getConfig();
|
|
const networkIp = await helpers.getLocalNetworkIp();
|
|
|
|
const connectionString = `mongodb://${config.MONGODB_USER}:${config.MONGODB_PASS}@${networkIp}:${config.MONGODB_PORT}/${config.MONGODB_NAME}?authSource=admin`;
|
|
|
|
logger.log('info', 'MongoDB Compass is a GUI tool for MongoDB. To connect:');
|
|
console.log();
|
|
logger.log('info', '1. Download MongoDB Compass from:');
|
|
logger.log('info', ' https://www.mongodb.com/products/compass');
|
|
console.log();
|
|
logger.log('info', '2. Open Compass and paste this connection string:');
|
|
logger.log('ok', ` ${connectionString}`);
|
|
console.log();
|
|
logger.log('note', 'Connection Details:');
|
|
logger.log('info', ` Network IP: ${networkIp}`);
|
|
logger.log('info', ` Port: ${config.MONGODB_PORT}`);
|
|
logger.log('info', ` Database: ${config.MONGODB_NAME}`);
|
|
logger.log('info', ` Username: ${config.MONGODB_USER}`);
|
|
logger.log('info', ` Auth Source: admin`);
|
|
}
|
|
|
|
/**
|
|
* Show logs for a service
|
|
*/
|
|
public async showLogs(service: string, lines: number = 20): Promise<void> {
|
|
const containers = this.config.getContainerNames();
|
|
|
|
switch (service) {
|
|
case 'mongo':
|
|
case 'mongodb':
|
|
if (await this.docker.isRunning(containers.mongo)) {
|
|
helpers.printHeader(`MongoDB Logs (last ${lines} lines)`);
|
|
const logs = await this.docker.logs(containers.mongo, lines);
|
|
console.log(logs);
|
|
} else {
|
|
logger.log('note', 'MongoDB container is not running');
|
|
}
|
|
break;
|
|
|
|
case 'minio':
|
|
case 's3':
|
|
if (await this.docker.isRunning(containers.minio)) {
|
|
helpers.printHeader(`S3/MinIO Logs (last ${lines} lines)`);
|
|
const logs = await this.docker.logs(containers.minio, lines);
|
|
console.log(logs);
|
|
} else {
|
|
logger.log('note', 'S3/MinIO container is not running');
|
|
}
|
|
break;
|
|
|
|
case 'all':
|
|
case '':
|
|
await this.showLogs('mongo', lines);
|
|
console.log();
|
|
await this.showLogs('minio', lines);
|
|
break;
|
|
|
|
default:
|
|
logger.log('note', 'Usage: gitzone services logs [mongo|s3|all] [lines]');
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove containers
|
|
*/
|
|
public async removeContainers(): Promise<void> {
|
|
const containers = this.config.getContainerNames();
|
|
let removed = false;
|
|
|
|
if (await this.docker.exists(containers.mongo)) {
|
|
if (await this.docker.remove(containers.mongo, true)) {
|
|
logger.log('ok', ' MongoDB container removed ✓');
|
|
removed = true;
|
|
}
|
|
}
|
|
|
|
if (await this.docker.exists(containers.minio)) {
|
|
if (await this.docker.remove(containers.minio, true)) {
|
|
logger.log('ok', ' S3/MinIO container removed ✓');
|
|
removed = true;
|
|
}
|
|
}
|
|
|
|
if (!removed) {
|
|
logger.log('note', ' No containers to remove');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clean data directories
|
|
*/
|
|
public async cleanData(): Promise<void> {
|
|
const directories = this.config.getDataDirectories();
|
|
let cleaned = false;
|
|
|
|
if (await plugins.smartfile.fs.fileExists(directories.mongo)) {
|
|
await plugins.smartfile.fs.remove(directories.mongo);
|
|
logger.log('ok', ' MongoDB data removed ✓');
|
|
cleaned = true;
|
|
}
|
|
|
|
if (await plugins.smartfile.fs.fileExists(directories.minio)) {
|
|
await plugins.smartfile.fs.remove(directories.minio);
|
|
logger.log('ok', ' S3/MinIO data removed ✓');
|
|
cleaned = true;
|
|
}
|
|
|
|
if (!cleaned) {
|
|
logger.log('note', ' No data to clean');
|
|
}
|
|
}
|
|
}
|