feat(dcrouter): add managed local dcrouter mode with status controls and gateway integration

This commit is contained in:
2026-05-09 20:04:02 +00:00
parent 595e84cdb6
commit dc37a71802
19 changed files with 873 additions and 31 deletions
+43
View File
@@ -164,6 +164,49 @@ Deno.test('ExternalGatewayManager syncs service routes to dcrouter gatewayClient
assertEquals(syncRequest.requestData.enabled, true);
});
Deno.test('ExternalGatewayManager uses managed dcrouter local target in managed mode', async () => {
const oneboxRef = makeOneboxRef();
(oneboxRef as any).managedDcRouter = {
getMode: () => 'managed',
getGatewayUrl: () => 'http://127.0.0.1:3300',
getAdminToken: async () => 'dcr-managed-token',
ensureGatewayClientId: () => 'onebox-managed',
getRouteTarget: () => ({ host: 'onebox-smartproxy', port: 80 }),
};
const service: IService = {
id: 1,
name: 'hello',
image: 'nginx:latest',
envVars: {},
port: 3000,
domain: 'hello.example.com',
status: 'running',
createdAt: 1,
updatedAt: 1,
};
let syncRequest: Record<string, unknown> | null = null;
const manager = new ExternalGatewayManager(oneboxRef as any);
(manager as any).fireDcRouterRequest = async (method: string, requestData: Record<string, unknown>, config: any) => {
if (method === 'exportCertificate') {
return { success: false };
}
assertEquals(config.url, 'http://127.0.0.1:3300');
assertEquals(config.apiToken, 'dcr-managed-token');
syncRequest = requestData;
return { success: true, action: 'created', routeId: 'route-1' };
};
await manager.syncServiceRoute(service);
assert(syncRequest);
const route = (syncRequest as Record<string, unknown>).route as any;
const ownership = (syncRequest as Record<string, unknown>).ownership as any;
assertEquals(ownership.gatewayClientId, 'onebox-managed');
assertEquals(route.action.targets, [{ host: 'onebox-smartproxy', port: 80 }]);
});
Deno.test('ExternalGatewayManager deletes service routes through dcrouter gatewayClient API', async () => {
const oneboxRef = makeOneboxRef();
const manager = new ExternalGatewayManager(oneboxRef as any);
+54
View File
@@ -0,0 +1,54 @@
import { assert, assertEquals } from '@std/assert';
import { ManagedDcRouterManager } from '../ts/classes/managed-dcrouter.ts';
class FakeDatabase {
public settings = new Map<string, string>();
public secretSettings = new Map<string, string>();
getSetting(key: string): string | null {
return this.settings.get(key) ?? null;
}
setSetting(key: string, value: string): void {
this.settings.set(key, value);
}
async getSecretSetting(key: string): Promise<string | null> {
return this.secretSettings.get(key) ?? null;
}
async setSecretSetting(key: string, value: string): Promise<void> {
this.secretSettings.set(key, value);
}
}
Deno.test('ManagedDcRouterManager persists default managed gateway settings', async () => {
const database = new FakeDatabase();
const manager = new ManagedDcRouterManager({ database } as any);
assertEquals(manager.getMode(), 'managed');
await manager.prepareGatewaySettings();
assertEquals(database.getSetting('dcrouterMode'), 'managed');
assertEquals(manager.getMode(), 'managed');
assertEquals(database.getSetting('dcrouterGatewayUrl'), 'http://127.0.0.1:3300');
assertEquals(database.getSetting('dcrouterTargetHost'), 'onebox-smartproxy');
assertEquals(database.getSetting('dcrouterTargetPort'), '80');
assert(database.getSetting('dcrouterGatewayClientId')?.startsWith('onebox-'));
assert((await database.getSecretSetting('dcrouterManagedAdminApiToken'))?.startsWith('dcr_'));
});
Deno.test('ManagedDcRouterManager keeps existing external gateway default external', async () => {
const database = new FakeDatabase();
database.setSetting('dcrouterGatewayUrl', 'https://edge.example.com');
const manager = new ManagedDcRouterManager({ database } as any);
assertEquals(manager.getMode(), 'external');
await manager.prepareGatewaySettings();
assertEquals(database.getSetting('dcrouterMode'), null);
assertEquals(database.getSetting('dcrouterTargetHost'), null);
});