feat(dns): Enhance DNS management with auto-generated entries and service activation

This commit is contained in:
2025-09-10 15:38:42 +00:00
parent 6a447369f8
commit fd1da01a3f
6 changed files with 190 additions and 1 deletions

View File

@@ -181,8 +181,16 @@ export class DeploymentManager {
throw new Error('Deployment not found');
}
const serviceId = deployment.serviceId;
await deployment.delete();
// Check if this was the last deployment for the service
const remainingDeployments = await this.getDeploymentsForService(serviceId);
if (remainingDeployments.length === 0) {
// Deactivate DNS entries if no more deployments exist
await this.cloudlyRef.dnsManager.deactivateServiceDnsEntries(serviceId);
}
return {
success: true,
};
@@ -281,7 +289,7 @@ export class DeploymentManager {
nodeId: string,
version: string = 'latest'
): Promise<Deployment> {
return await Deployment.createDeployment({
const deployment = await Deployment.createDeployment({
serviceId,
nodeId,
version,
@@ -289,6 +297,19 @@ export class DeploymentManager {
deployedAt: Date.now(),
deploymentLog: [`Deployment created at ${new Date().toISOString()}`],
});
// Activate DNS entries for the service
await this.cloudlyRef.dnsManager.activateServiceDnsEntries(serviceId);
// Get the node's IP address and update DNS entries
const node = await this.cloudlyRef.nodeManager.CClusterNode.getInstance({
id: nodeId,
});
if (node && node.data.publicIp) {
await this.cloudlyRef.dnsManager.updateServiceDnsEntriesIp(serviceId, node.data.publicIp);
}
return deployment;
}
public async start() {

View File

@@ -156,6 +156,95 @@ export class DnsManager {
);
}
/**
* Create a DNS entry for a service
* @param dnsEntryData The DNS entry data
*/
public async createServiceDnsEntry(dnsEntryData: plugins.servezoneInterfaces.data.IDnsEntry['data']) {
// If domainId is provided, get the domain and set the zone
if (dnsEntryData.domainId) {
const domain = await this.cloudlyRef.domainManager.CDomain.getInstance({
id: dnsEntryData.domainId,
});
if (domain) {
dnsEntryData.zone = domain.data.name;
}
}
// Create the DNS entry
const dnsEntry = await this.CDnsEntry.createDnsEntry(dnsEntryData);
return dnsEntry;
}
/**
* Activate DNS entries for a service when it's deployed
* @param serviceId The service ID
*/
public async activateServiceDnsEntries(serviceId: string) {
const dnsEntries = await this.CDnsEntry.getInstances({
'data.sourceServiceId': serviceId,
'data.sourceType': 'service',
});
for (const entry of dnsEntries) {
entry.data.active = true;
entry.data.updatedAt = Date.now();
await entry.save();
}
}
/**
* Deactivate DNS entries for a service when it's undeployed
* @param serviceId The service ID
*/
public async deactivateServiceDnsEntries(serviceId: string) {
const dnsEntries = await this.CDnsEntry.getInstances({
'data.sourceServiceId': serviceId,
'data.sourceType': 'service',
});
for (const entry of dnsEntries) {
entry.data.active = false;
entry.data.updatedAt = Date.now();
await entry.save();
}
}
/**
* Remove all DNS entries for a service
* @param serviceId The service ID
*/
public async removeServiceDnsEntries(serviceId: string) {
const dnsEntries = await this.CDnsEntry.getInstances({
'data.sourceServiceId': serviceId,
'data.sourceType': 'service',
});
for (const entry of dnsEntries) {
await entry.delete();
}
}
/**
* Update DNS entry values when deployment happens
* @param serviceId The service ID
* @param ipAddress The IP address to set for the DNS entries
*/
public async updateServiceDnsEntriesIp(serviceId: string, ipAddress: string) {
const dnsEntries = await this.CDnsEntry.getInstances({
'data.sourceServiceId': serviceId,
'data.sourceType': 'service',
});
for (const entry of dnsEntries) {
if (entry.data.type === 'A' || entry.data.type === 'AAAA') {
entry.data.value = ipAddress;
entry.data.updatedAt = Date.now();
await entry.save();
}
}
}
/**
* Initialize the DNS manager
*/

View File

@@ -25,6 +25,12 @@ export class Service extends plugins.smartdata.SmartDataDbDoc<
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;
}
@@ -54,4 +60,40 @@ export class Service extends plugins.smartdata.SmartDataDbDoc<
}
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);
}
}

View File

@@ -91,6 +91,10 @@ export class ServiceManager {
const service = await Service.getInstance({
id: dataArg.serviceId,
});
// Remove DNS entries before deleting the service
await service.removeDnsEntries();
await service.delete();
return {
success: true,