Files
cloudly/ts/manager.service/classes.service.ts
Juergen Kunz 5b37bb5b11 feat: Implement Cloudly Task Manager with predefined tasks and execution tracking
- Added CloudlyTaskManager class for managing tasks, including registration, execution, scheduling, and cancellation.
- Created predefined tasks: DNS Sync, Certificate Renewal, Cleanup, Health Check, Resource Report, Database Maintenance, Security Scan, and Docker Cleanup.
- Introduced ITaskExecution interface for tracking task execution details and outcomes.
- Developed API request interfaces for task management operations (getTasks, getTaskExecutions, triggerTask, cancelTask).
- Implemented CloudlyViewTasks web component for displaying tasks and their execution history, including filtering and detailed views.
2025-09-10 16:37:03 +00:00

101 lines
3.3 KiB
TypeScript

import { SecretBundle } from 'ts/manager.secret/classes.secretbundle.js';
import * as plugins from '../plugins.js';
import { ServiceManager } from './classes.servicemanager.js';
@plugins.smartdata.managed()
export class Service extends plugins.smartdata.SmartDataDbDoc<
Service,
plugins.servezoneInterfaces.data.IService,
ServiceManager
> {
// STATIC
public static async getServiceById(serviceIdArg: string) {
const service = await this.getInstance({
id: serviceIdArg,
});
return service;
}
public static async getServices() {
const services = await this.getInstances({});
return services;
}
public static async createService(serviceDataArg: Partial<plugins.servezoneInterfaces.data.IService['data']>) {
const service = new Service();
service.id = await Service.getNewId();
Object.assign(service, serviceDataArg);
await service.save();
// Create DNS entries if service has web port and domains configured
if (service.data.ports?.web && service.data.domains?.length > 0) {
await service.createDnsEntries();
}
return service;
}
// INSTANCE
@plugins.smartdata.svDb()
public id: string;
@plugins.smartdata.svDb()
public data: plugins.servezoneInterfaces.data.IService['data'];
/**
* a service runs in a specific environment
* so -> this method returns the secret bundles as a flat object accordingly.
* in other words, it resolves secret groups for the relevant environment
* @param environmentArg
*/
public async getSecretBundlesAsFlatObject(environmentArg: string = 'production') {
const secreBundleIds = this.data.additionalSecretBundleIds || [];
secreBundleIds.push(this.data.secretBundleId); // put this last, so it overwrites any other secret bundles.
let finalFlatObject = {};
for (const secretBundleId of secreBundleIds) {
const secretBundle = await SecretBundle.getInstance({
id: secretBundleId,
});
const flatObject = await secretBundle.getFlatKeyValueObject(environmentArg);
Object.assign(finalFlatObject, flatObject);
}
return finalFlatObject;
}
/**
* Creates DNS entries for this service (in inactive state)
* These will be activated when the service is deployed
*/
public async createDnsEntries() {
const dnsManager = this.manager.cloudlyRef.dnsManager;
for (const domain of this.data.domains) {
const dnsEntryData: plugins.servezoneInterfaces.data.IDnsEntry['data'] = {
type: 'A', // Default to A record, could be made configurable
name: domain.name,
value: '0.0.0.0', // Placeholder, will be updated on deployment
ttl: 3600,
zone: '', // Will be set based on domainId
domainId: domain.domainId,
active: false, // Created as inactive
description: `Auto-generated DNS entry for service ${this.data.name}`,
createdAt: Date.now(),
isAutoGenerated: true,
sourceServiceId: this.id,
sourceType: 'service',
};
// Create the DNS entry
await dnsManager.createServiceDnsEntry(dnsEntryData);
}
}
/**
* Removes DNS entries for this service
*/
public async removeDnsEntries() {
const dnsManager = this.manager.cloudlyRef.dnsManager;
await dnsManager.removeServiceDnsEntries(this.id);
}
}