UNPKG

@multicloud-io/multicloud-connection-js

Version:

Shared TypeScript/JavaScript library for connecting to Multicloud servers with mTLS authentication

557 lines 21.3 kB
"use strict"; /** * Multicloud REST API client * * Provides a comprehensive client for interacting with Multicloud servers * with mTLS authentication and proper error handling. * * IMPORTANT: This is for server-side use only - never expose to client/browser! */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MulticloudRestClient = exports.LegacyConstraintType = exports.ConstraintType = exports.TaskAssignmentType = exports.VolumeDescSyncMode = exports.VolumeDescAccessMode = exports.TaskStatus = exports.ProcessorArchitecture = exports.ServerStatus = exports.Orchestration = exports.State = exports.ExtendedLocationRuleType = void 0; const https_1 = __importDefault(require("https")); const fs_1 = __importDefault(require("fs")); const exceptions_1 = require("./exceptions"); /** * ExtendedLocationRuleType enum for location rules */ var ExtendedLocationRuleType; (function (ExtendedLocationRuleType) { ExtendedLocationRuleType["INCLUDE_ALL_PROVIDER"] = "INCLUDE_ALL_PROVIDER"; ExtendedLocationRuleType["EXCLUDE_ALL_PROVIDER"] = "EXCLUDE_ALL_PROVIDER"; ExtendedLocationRuleType["INCLUDE_REGION"] = "INCLUDE_REGION"; ExtendedLocationRuleType["EXCLUDE_REGION"] = "EXCLUDE_REGION"; ExtendedLocationRuleType["INCLUDE_PROVIDER_REGION"] = "INCLUDE_PROVIDER_REGION"; ExtendedLocationRuleType["EXCLUDE_PROVIDER_REGION"] = "EXCLUDE_PROVIDER_REGION"; ExtendedLocationRuleType["INCLUDE_LOCATION"] = "INCLUDE_LOCATION"; ExtendedLocationRuleType["EXCLUDE_LOCATION"] = "EXCLUDE_LOCATION"; ExtendedLocationRuleType["INCLUDE_ZONE"] = "INCLUDE_ZONE"; ExtendedLocationRuleType["EXCLUDE_ZONE"] = "EXCLUDE_ZONE"; ExtendedLocationRuleType["INCLUDE_PROVIDER_ZONE"] = "INCLUDE_PROVIDER_ZONE"; ExtendedLocationRuleType["EXCLUDE_PROVIDER_ZONE"] = "EXCLUDE_PROVIDER_ZONE"; })(ExtendedLocationRuleType || (exports.ExtendedLocationRuleType = ExtendedLocationRuleType = {})); /** * State enum for job states */ var State; (function (State) { State["LOADED"] = "LOADED"; State["STARTING"] = "STARTING"; State["RUNNING"] = "RUNNING"; State["STOPPING"] = "STOPPING"; State["STOPPED"] = "STOPPED"; State["PENDING_DESTROY"] = "PENDING_DESTROY"; State["DONE"] = "DONE"; State["ERROR"] = "ERROR"; })(State || (exports.State = State = {})); /** * Orchestration enum for job orchestration types */ var Orchestration; (function (Orchestration) { Orchestration["EXTERNAL"] = "EXTERNAL"; Orchestration["ALL"] = "ALL"; Orchestration["EXACTLY"] = "EXACTLY"; Orchestration["ACTIVE_STANDBY"] = "ACTIVE_STANDBY"; Orchestration["EXACTLY_ONCE"] = "EXACTLY_ONCE"; Orchestration["CRON"] = "CRON"; })(Orchestration || (exports.Orchestration = Orchestration = {})); /** * ServerStatus enum */ var ServerStatus; (function (ServerStatus) { ServerStatus["PENDING"] = "PENDING"; ServerStatus["UNKNOWN"] = "UNKNOWN"; ServerStatus["INITIALIZING"] = "INITIALIZING"; ServerStatus["STARTING"] = "STARTING"; ServerStatus["RUNNING"] = "RUNNING"; ServerStatus["STOPPING"] = "STOPPING"; ServerStatus["STOPPED"] = "STOPPED"; ServerStatus["ERROR"] = "ERROR"; ServerStatus["PENDING_SHUTDOWN"] = "PENDING_SHUTDOWN"; ServerStatus["TERMINATED"] = "TERMINATED"; })(ServerStatus || (exports.ServerStatus = ServerStatus = {})); /** * ProcessorArchitecture enum */ var ProcessorArchitecture; (function (ProcessorArchitecture) { ProcessorArchitecture["X86_64"] = "X86_64"; ProcessorArchitecture["ARM64"] = "ARM64"; ProcessorArchitecture["UNKNOWN"] = "UNKNOWN"; })(ProcessorArchitecture || (exports.ProcessorArchitecture = ProcessorArchitecture = {})); /** * TaskStatus enum */ var TaskStatus; (function (TaskStatus) { TaskStatus["UNKNOWN"] = "UNKNOWN"; TaskStatus["PENDING"] = "PENDING"; TaskStatus["PENDING_UNASSIGNABLE"] = "PENDING_UNASSIGNABLE"; TaskStatus["ASSIGNED"] = "ASSIGNED"; TaskStatus["STARTING"] = "STARTING"; TaskStatus["RUNNING"] = "RUNNING"; TaskStatus["RESTARTING"] = "RESTARTING"; TaskStatus["STOPPING"] = "STOPPING"; TaskStatus["STOPPED"] = "STOPPED"; TaskStatus["DONE"] = "DONE"; TaskStatus["ERROR"] = "ERROR"; TaskStatus["PENDING_SHUTDOWN"] = "PENDING_SHUTDOWN"; TaskStatus["PENDING_RESTART"] = "PENDING_RESTART"; TaskStatus["CANCELLED"] = "CANCELLED"; })(TaskStatus || (exports.TaskStatus = TaskStatus = {})); /** * VolumeDesc access mode enum matching Java AccessMode */ var VolumeDescAccessMode; (function (VolumeDescAccessMode) { VolumeDescAccessMode["RW"] = "rw"; VolumeDescAccessMode["RO"] = "ro"; })(VolumeDescAccessMode || (exports.VolumeDescAccessMode = VolumeDescAccessMode = {})); /** * VolumeDesc sync mode enum matching Java SyncMode */ var VolumeDescSyncMode; (function (VolumeDescSyncMode) { VolumeDescSyncMode["NEVER"] = "NEVER"; VolumeDescSyncMode["ON_EXIT"] = "ON_EXIT"; VolumeDescSyncMode["CONTINUOUS"] = "CONTINUOUS"; VolumeDescSyncMode["PERIODIC"] = "PERIODIC"; VolumeDescSyncMode["ON_MIGRATION"] = "ON_MIGRATION"; })(VolumeDescSyncMode || (exports.VolumeDescSyncMode = VolumeDescSyncMode = {})); /** * TaskAssignmentType enum */ var TaskAssignmentType; (function (TaskAssignmentType) { TaskAssignmentType["NEW_TASK"] = "NEW_TASK"; TaskAssignmentType["TASK_UPDATE"] = "TASK_UPDATE"; TaskAssignmentType["TASK_STOP"] = "TASK_STOP"; })(TaskAssignmentType || (exports.TaskAssignmentType = TaskAssignmentType = {})); /** * Constraint type enum matching the Java constraint system */ var ConstraintType; (function (ConstraintType) { // Resource constraints ConstraintType["SERVER_RESOURCES"] = "serverResources"; ConstraintType["REQUIRES_MEMORY"] = "requiresMemory"; ConstraintType["REQUIRES_GPU"] = "requiresGpu"; ConstraintType["REQUIRES_CPU_CORES"] = "requiresCpuCores"; ConstraintType["CPU_BENCHMARK"] = "cpuBenchmark"; // Job dependency constraints ConstraintType["AFTER_JOB"] = "afterJob"; ConstraintType["BEFORE_JOB"] = "beforeJob"; ConstraintType["AT_TIME"] = "atTime"; })(ConstraintType || (exports.ConstraintType = ConstraintType = {})); /** * Legacy ConstraintType enum (deprecated - use new ConstraintType instead) * @deprecated Use ConstraintType instead */ var LegacyConstraintType; (function (LegacyConstraintType) { LegacyConstraintType["AFTER"] = "after"; LegacyConstraintType["BEFORE"] = "before"; LegacyConstraintType["AT"] = "at"; LegacyConstraintType["REQUIRES"] = "requires"; })(LegacyConstraintType || (exports.LegacyConstraintType = LegacyConstraintType = {})); /** * Multicloud REST API client */ class MulticloudRestClient { constructor(params, debug = false) { this.params = params; this.debug = debug; } /** * Make an authenticated request to the Multicloud API */ async makeRequest(method, path, body) { const url = `${this.params.serverUrl}${path}`; // Log request details in non-production environments // if (process.env.NODE_ENV !== 'production') { // console.log(`[MulticloudRESTClient] ${method} ${url}`); // if (body) { // console.log(`[MulticloudRESTClient] Request body:`, JSON.stringify(body, null, 2)); // } // } // Build headers object const headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' }; // Add Authorization header if accessToken is provided if (this.params.accessToken) { headers['Authorization'] = `Bearer ${this.params.accessToken}`; // if (this.debug) { // console.log(`[MulticloudRESTClient] Added Authorization header with token length: ${this.params.accessToken.length}`); // } } else if (this.debug) { console.log('[MulticloudRESTClient] No accessToken provided, skipping Authorization header'); } const options = { method, headers }; // Add client certificates if provided if (this.params.clientCert && this.params.clientKey) { options.cert = fs_1.default.readFileSync(this.params.clientCert); options.key = fs_1.default.readFileSync(this.params.clientKey); } // Log headers in debug mode // if (this.debug) { // console.log(`[MulticloudRESTClient] Request headers:`, options.headers); // } return new Promise((resolve, reject) => { const req = https_1.default.request(url, options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { if (this.debug) { console.log(`[MulticloudRESTClient] ${method} ${path} -> ${res.statusCode}`); } if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { try { const result = data ? JSON.parse(data) : null; resolve(result); } catch (error) { reject(new exceptions_1.MulticloudResponseError(`Failed to parse response: ${error}`)); } } else { reject(new exceptions_1.MulticloudResponseError(`HTTP ${res.statusCode}: ${data}`)); } }); }); req.on('error', (error) => { reject(new exceptions_1.MulticloudNetworkError(`Request failed: ${error.message}`)); }); if (body) { req.write(JSON.stringify(body)); } req.end(); }); } /** * Test connection to the Multicloud server */ async testConnection() { try { // Try to get a simple endpoint to test connectivity await this.makeRequest('GET', '/health'); return true; } catch (error) { if (this.debug) { console.log('[MulticloudRESTClient] Connection test failed:', error); } throw error; } } /** * Health check endpoints */ async pingCoordinator() { return this.makeRequest('GET', '/coordinator/ping'); } async pingAdmin() { return this.makeRequest('GET', '/admin/ping'); } async pingApplications() { return this.makeRequest('GET', '/applications/ping'); } /** * Application management endpoints */ async getApplications() { return this.makeRequest('GET', '/applications'); } async getApplication(applicationId) { return this.makeRequest('GET', `/applications/${applicationId}`); } async createApplication(application) { return this.makeRequest('POST', '/applications', application); } async updateApplication(applicationId, application) { return this.makeRequest('PUT', `/applications/${applicationId}`, application); } async deleteApplication(applicationId) { return this.makeRequest('DELETE', `/applications/${applicationId}`); } async getApplicationJobs(applicationId) { return this.makeRequest('GET', `/applications/jobs?applicationId=${applicationId}`); } async getApplicationClusters(applicationId) { return this.makeRequest('GET', `/applications/clusters?applicationId=${applicationId}`); } /** * Job management endpoints */ async getJobs(clusterId) { const path = clusterId ? `/coordinator/jobs?clusterId=${clusterId}` : '/coordinator/jobs'; return this.makeRequest('GET', path); } async getJob(jobId) { return this.makeRequest('GET', `/coordinator/job/${jobId}`); } async addJobs(jobs, clusterId) { const path = clusterId ? `/coordinator/jobs?clusterId=${clusterId}` : '/coordinator/jobs'; return this.makeRequest('POST', path, jobs); } async addJob(job) { return this.makeRequest('POST', '/coordinator/job', job); } async updateJob(jobId, job) { return this.makeRequest('PUT', `/coordinator/job/${jobId}`, job); } async jobAction(jobId, action, clusterId, scaleBy) { const params = new URLSearchParams(); params.append('action', action); if (clusterId) params.append('clusterId', clusterId.toString()); if (scaleBy !== undefined) params.append('by', scaleBy.toString()); return this.makeRequest('PUT', `/coordinator/job/${jobId}?${params.toString()}`); } async deleteJob(jobId) { return this.makeRequest('DELETE', `/coordinator/jobs/${jobId}`); } async getJobTasks(jobId) { return this.makeRequest('GET', `/coordinator/jobs/${jobId}/tasks`); } async getJobByOwner(owner, jobId) { const path = jobId ? `/coordinator/jobs/owner/${owner}?jobId=${jobId}` : `/coordinator/jobs/owner/${owner}`; return this.makeRequest('GET', path); } /** * Cluster management endpoints */ async getClusters() { return this.makeRequest('GET', '/admin/clusters'); } async getCluster(clusterId) { return this.makeRequest('GET', `/coordinator/cluster/${clusterId}`); } async createCluster(cluster) { return this.makeRequest('POST', '/coordinator/cluster', cluster); } async addOrUpdateClusters(clusters) { return this.makeRequest('POST', '/coordinator/cluster', clusters); } async updateCluster(clusterId, cluster) { return this.makeRequest('PUT', `/coordinator/clusters/${clusterId}`, cluster); } async deleteCluster(clusterId) { return this.makeRequest('DELETE', `/coordinator/clusters/${clusterId}`); } async getClusterJobs(clusterId) { return this.makeRequest('GET', `/coordinator/jobs?clusterId=${clusterId}`); } async getClusterServers(clusterId) { return this.makeRequest('GET', `/admin/servers?clusterId=${clusterId}`); } async getClusterLocations(clusterId) { return this.makeRequest('GET', `/admin/cluster/${clusterId}/locations`); } /** * Server management endpoints */ async getServers(clusterId) { const path = clusterId ? `/admin/servers?clusterId=${clusterId}` : '/admin/servers'; return this.makeRequest('GET', path); } async getServer(clusterId, serverId) { return this.makeRequest('GET', `/admin/cluster/${clusterId}/server/${serverId}`); } async updateServer(serverId, server) { return this.makeRequest('PUT', `/coordinator/servers/${serverId}`, server); } async deleteServer(serverId) { return this.makeRequest('DELETE', `/coordinator/servers/${serverId}`); } // Note: Backend does not support getting tasks by serverId directly // Use getTasks() with jobId and clusterId parameters instead async getServerTasks(serverId) { // This endpoint doesn't exist in the backend - would need to be implemented throw new Error('getServerTasks not supported by backend - use getTasks() with jobId/clusterId instead'); } /** * Server resource offer endpoint (used by agents) */ async offerResources(server) { return this.makeRequest('POST', '/coordinator/offer', server); } /** * Task management endpoints */ async getTasks(clusterId, jobId) { let path = '/coordinator/tasks'; const params = new URLSearchParams(); if (clusterId) params.append('clusterId', clusterId.toString()); if (jobId) params.append('jobId', jobId.toString()); if (params.toString()) path += `?${params.toString()}`; return this.makeRequest('GET', path); } async getTask(taskId) { return this.makeRequest('GET', `/coordinator/tasks/${taskId}`); } async updateTask(task) { return this.makeRequest('POST', '/coordinator/task', task); } async deleteTask(taskId) { return this.makeRequest('DELETE', `/coordinator/tasks/${taskId}`); } async getTasksByOwner(owner) { return this.makeRequest('GET', `/coordinator/tasks/owner/${owner}`); } async restartJobTasks(jobId, clusterId) { const params = new URLSearchParams(); params.append('jobId', jobId.toString()); if (clusterId) params.append('clusterId', clusterId.toString()); return this.makeRequest('POST', `/coordinator/cli/job/restart?${params.toString()}`); } async restartTask(taskIds) { const params = new URLSearchParams(); taskIds.forEach(id => params.append('taskId', id.toString())); return this.makeRequest('POST', `/coordinator/cli/task/restart?${params.toString()}`); } /** * IP Lease management endpoints */ async getIpLeases(subnetName, serviceName) { let path = '/coordinator/ip-leases'; const params = new URLSearchParams(); if (subnetName) params.append('subnetName', subnetName); if (serviceName) params.append('serviceName', serviceName); if (params.toString()) path += `?${params.toString()}`; return this.makeRequest('GET', path); } async getIpLease(subnetName, serviceName) { return this.makeRequest('GET', `/coordinator/ip-leases/${subnetName}/${serviceName}`); } async createIpLease(ipLease) { return this.makeRequest('POST', '/coordinator/ip-leases', ipLease); } async updateIpLease(subnetName, serviceName, ipLease) { return this.makeRequest('PUT', `/coordinator/ip-leases/${subnetName}/${serviceName}`, ipLease); } async deleteIpLease(subnetName, serviceName) { return this.makeRequest('DELETE', `/coordinator/ip-leases/${subnetName}/${serviceName}`); } /** * Location management endpoints */ async getLocations() { return this.makeRequest('GET', '/coordinator/locations'); } async getLocation(locationId) { return this.makeRequest('GET', `/coordinator/locations/${locationId}`); } /** * Cloud provider management endpoints */ async getCloudProviders() { return this.makeRequest('GET', '/coordinator/cloud-providers'); } async getCloudProvider(providerId) { return this.makeRequest('GET', `/coordinator/cloud-providers/${providerId}`); } /** * Key pair management endpoints */ async getKeyPairs() { return this.makeRequest('GET', '/coordinator/key-pairs'); } async getKeyPair(keyPairId) { return this.makeRequest('GET', `/coordinator/key-pairs/${keyPairId}`); } /** * Service management endpoints */ async getServices() { return this.makeRequest('GET', '/coordinator/services'); } async getService(serviceId) { return this.makeRequest('GET', `/coordinator/services/${serviceId}`); } /** * Volume management endpoints */ async getVolumes() { return this.makeRequest('GET', '/coordinator/volumes'); } async getVolume(volumeId) { return this.makeRequest('GET', `/coordinator/volumes/${volumeId}`); } /** * Property management endpoints */ async getProperties() { return this.makeRequest('GET', '/coordinator/properties'); } async getProperty(propertyId) { return this.makeRequest('GET', `/coordinator/properties/${propertyId}`); } /** * Unit management endpoints */ async getUnits() { return this.makeRequest('GET', '/coordinator/units'); } async getUnit(unitId) { return this.makeRequest('GET', `/coordinator/units/${unitId}`); } /** * Route53 management endpoints */ async getRoute53Records() { return this.makeRequest('GET', '/coordinator/route53'); } async getRoute53Record(recordId) { return this.makeRequest('GET', `/coordinator/route53/${recordId}`); } /** * Admin endpoints */ async getAdminStats() { return this.makeRequest('GET', '/admin/stats'); } async getAdminHealth() { return this.makeRequest('GET', '/admin/health'); } async getAdminMetrics() { return this.makeRequest('GET', '/admin/metrics'); } /** * Catalog endpoints */ async getCatalogServerTypes() { return this.makeRequest('GET', '/catalog/server-types'); } async getCatalogServerType(serverTypeId) { return this.makeRequest('GET', `/catalog/server-types/${serverTypeId}`); } async getCatalogProcessors() { return this.makeRequest('GET', '/catalog/processors'); } async getCatalogAccelerators() { return this.makeRequest('GET', '/catalog/accelerators'); } } exports.MulticloudRestClient = MulticloudRestClient; //# sourceMappingURL=client.js.map