feat: Implement platform service providers for MinIO and MongoDB

- Added base interface and abstract class for platform service providers.
- Created MinIOProvider class for S3-compatible storage with deployment, provisioning, and deprovisioning functionalities.
- Implemented MongoDBProvider class for MongoDB service with similar capabilities.
- Introduced error handling utilities for better error management.
- Developed TokensComponent for managing registry tokens in the UI, including creation, deletion, and display of tokens.
This commit is contained in:
2025-11-25 04:20:19 +00:00
parent 9aa6906ca5
commit 8ebd677478
28 changed files with 3462 additions and 490 deletions

View File

@@ -841,4 +841,89 @@ export class OneboxDockerManager {
throw error;
}
}
/**
* Create a platform service container (MongoDB, MinIO, etc.)
* Platform containers are long-running infrastructure services
*/
async createPlatformContainer(options: {
name: string;
image: string;
port: number;
env: string[];
volumes?: string[];
network: string;
command?: string[];
exposePorts?: number[];
}): Promise<string> {
try {
logger.info(`Creating platform container: ${options.name}`);
// Check if container already exists
const existingContainers = await this.dockerClient!.listContainers();
const existing = existingContainers.find((c: any) =>
c.Names?.some((n: string) => n === `/${options.name}` || n === options.name)
);
if (existing) {
logger.info(`Platform container ${options.name} already exists, removing old container...`);
await this.removeContainer(existing.Id, true);
}
// Prepare exposed ports
const exposedPorts: Record<string, Record<string, never>> = {};
const portBindings: Record<string, Array<{ HostIp: string; HostPort: string }>> = {};
const portsToExpose = options.exposePorts || [options.port];
for (const port of portsToExpose) {
exposedPorts[`${port}/tcp`] = {};
// Don't bind to host ports by default - services communicate via Docker network
portBindings[`${port}/tcp`] = [];
}
// Prepare volume bindings
const binds: string[] = options.volumes || [];
// Create the container
const response = await this.dockerClient!.request('POST', `/containers/create?name=${options.name}`, {
Image: options.image,
Cmd: options.command,
Env: options.env,
Labels: {
'managed-by': 'onebox',
'onebox-platform-service': options.name,
},
ExposedPorts: exposedPorts,
HostConfig: {
NetworkMode: options.network,
RestartPolicy: {
Name: 'unless-stopped',
},
PortBindings: portBindings,
Binds: binds,
},
});
if (response.statusCode >= 300) {
const errorMsg = response.body?.message || `HTTP ${response.statusCode}`;
throw new Error(`Failed to create platform container: ${errorMsg}`);
}
const containerID = response.body.Id;
logger.info(`Platform container created: ${containerID}`);
// Start the container
const startResponse = await this.dockerClient!.request('POST', `/containers/${containerID}/start`, {});
if (startResponse.statusCode >= 300 && startResponse.statusCode !== 304) {
throw new Error(`Failed to start platform container: HTTP ${startResponse.statusCode}`);
}
logger.success(`Platform container ${options.name} started successfully`);
return containerID;
} catch (error) {
logger.error(`Failed to create platform container ${options.name}: ${error.message}`);
throw error;
}
}
}