feat: sync workload routes to external gateway
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import * as plugins from './coreflow.plugins.js';
|
||||
import { Coreflow } from './coreflow.classes.coreflow.js';
|
||||
import { logger } from './coreflow.logging.js';
|
||||
|
||||
export interface IExternalGatewayConfig {
|
||||
url: string;
|
||||
apiToken: string;
|
||||
workHosterType: 'cloudly';
|
||||
workHosterId: string;
|
||||
targetHost?: string;
|
||||
targetPort?: number;
|
||||
}
|
||||
|
||||
interface IWorkAppRouteSyncResult {
|
||||
success: boolean;
|
||||
action?: 'created' | 'updated' | 'deleted' | 'unchanged';
|
||||
routeId?: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
interface IDcRouterCertificateExport {
|
||||
success: boolean;
|
||||
cert?: {
|
||||
id: string;
|
||||
domainName: string;
|
||||
created: number;
|
||||
validUntil: number;
|
||||
privateKey: string;
|
||||
publicKey: string;
|
||||
csr: string;
|
||||
};
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export class ExternalGatewayConnector {
|
||||
constructor(public coreflowRef: Coreflow) {}
|
||||
|
||||
public isConfigured(configArg?: IExternalGatewayConfig): configArg is IExternalGatewayConfig {
|
||||
return Boolean(
|
||||
configArg?.url
|
||||
&& configArg.apiToken
|
||||
&& configArg.workHosterId
|
||||
&& configArg.targetHost
|
||||
&& configArg.targetPort,
|
||||
);
|
||||
}
|
||||
|
||||
public async syncWorkAppRoute(optionsArg: {
|
||||
config: IExternalGatewayConfig | undefined;
|
||||
service: plugins.servezoneInterfaces.data.IService;
|
||||
hostname: string;
|
||||
}): Promise<void> {
|
||||
const config = optionsArg.config;
|
||||
if (!this.isConfigured(config)) return;
|
||||
|
||||
const result = await this.fireDcRouterRequest<IWorkAppRouteSyncResult>(
|
||||
config,
|
||||
'syncWorkAppRoute',
|
||||
{
|
||||
ownership: {
|
||||
workHosterType: 'cloudly',
|
||||
workHosterId: config.workHosterId,
|
||||
workAppId: optionsArg.service.id || optionsArg.service.data.name,
|
||||
hostname: optionsArg.hostname,
|
||||
},
|
||||
route: {
|
||||
name: this.routeName(optionsArg.hostname),
|
||||
match: {
|
||||
ports: [443],
|
||||
domains: [optionsArg.hostname],
|
||||
},
|
||||
action: {
|
||||
type: 'forward',
|
||||
targets: [{ host: config.targetHost!, port: config.targetPort! }],
|
||||
tls: {
|
||||
mode: 'terminate',
|
||||
certificate: 'auto',
|
||||
},
|
||||
websocket: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
enabled: true,
|
||||
},
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.message || `dcrouter route sync failed for ${optionsArg.hostname}`);
|
||||
}
|
||||
|
||||
logger.log('success', `external gateway route ${result.action || 'synced'} for ${optionsArg.hostname}`);
|
||||
}
|
||||
|
||||
public async exportCertificateForDomain(
|
||||
configArg: IExternalGatewayConfig | undefined,
|
||||
hostnameArg: string,
|
||||
): Promise<plugins.tsclass.network.ICert | undefined> {
|
||||
if (!configArg?.url || !configArg.apiToken) return undefined;
|
||||
|
||||
const result = await this.fireDcRouterRequest<IDcRouterCertificateExport>(
|
||||
configArg,
|
||||
'exportCertificate',
|
||||
{ domain: hostnameArg },
|
||||
);
|
||||
|
||||
if (!result.success || !result.cert) return undefined;
|
||||
return {
|
||||
id: result.cert.id,
|
||||
domainName: result.cert.domainName,
|
||||
created: result.cert.created,
|
||||
validUntil: result.cert.validUntil,
|
||||
privateKey: result.cert.privateKey,
|
||||
publicKey: result.cert.publicKey,
|
||||
csr: result.cert.csr,
|
||||
};
|
||||
}
|
||||
|
||||
private routeName(hostnameArg: string): string {
|
||||
return `cloudly-${hostnameArg.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-|-$/g, '')}`;
|
||||
}
|
||||
|
||||
private async fireDcRouterRequest<TResponse>(
|
||||
configArg: IExternalGatewayConfig,
|
||||
methodArg: string,
|
||||
requestDataArg: Record<string, unknown>,
|
||||
): Promise<TResponse> {
|
||||
const typedRequest = new plugins.typedrequest.TypedRequest<any>(
|
||||
`${configArg.url.replace(/\/+$/, '')}/typedrequest`,
|
||||
methodArg,
|
||||
);
|
||||
return await typedRequest.fire({
|
||||
...requestDataArg,
|
||||
apiToken: configArg.apiToken,
|
||||
}) as TResponse;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user