Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import { decodeRuntimeHostOwnerConnectionCode } from '@maka/runtime-host/client';
import { resolveRuntimeHostManagedServiceId } from '@maka/runtime-host/operator';
import type { RuntimeHostDesktopManager } from '../runtime-host-desktop-manager.js';

const RECOVERY_DEPLOYMENT_ID = '33333333-3333-4333-8333-333333333333';
import { createDesktopLocalRuntimeHostRemoteAccess } from '../runtime-host-local-remote-access.js';
import type { createDesktopRuntimeHostLocalOperator } from '../runtime-host-local-operator.js';

Expand All @@ -33,7 +34,6 @@ test('enabling remote access hands the same root to one managed service before D
t.after(() => rm(base, { recursive: true, force: true }));
const clientDataRoot = join(base, 'client');
const rootPath = join(clientDataRoot, 'workspaces', 'default');
const serviceId = resolveRuntimeHostManagedServiceId(clientDataRoot);
await mkdir(rootPath, { recursive: true });
const handlers = new Map<string, Parameters<Electron.IpcMain['handle']>[1]>();
let retired = false;
Expand All @@ -49,16 +49,27 @@ test('enabling remote access hands the same root to one managed service before D
routeHints: ['/ip4/192.0.2.1/udp/41000/quic-v1'],
coordinationRelays: [],
};
const deploymentId = '11111111-1111-4111-8111-111111111111';
const operator = {
async runSetup(input: { readonly rootPath: string; readonly principalId: string }) {
async runSetup(input: {
readonly rootPath: string;
readonly principalId: string;
readonly expectedTarget: { readonly serviceId: string; readonly rootId: string };
}) {
assert.equal(retired, true);
assert.equal(input.rootPath, rootPath);
assert.equal(input.principalId, 'desktop-owner:local-runtime-host-sharing');
assert.deepEqual(input.expectedTarget, {
serviceId: 'a'.repeat(64),
rootPath,
rootId: 'a'.repeat(64),
});
return {
serviceId,
serviceId: 'a'.repeat(64),
operatorPath: join(base, 'operator'),
rootPath,
rootId: 'a'.repeat(64),
deploymentId,
credential: 'pending-credential',
directPeer: peer,
};
Expand Down Expand Up @@ -109,11 +120,12 @@ test('enabling remote access hands the same root to one managed service before D
transport: { kind: 'libp2p-direct', ...peer },
credential: 'pending-credential',
});
assert.equal(
JSON.parse(await readFile(join(clientDataRoot, 'runtime-host-local-service.json'), 'utf8'))
.state,
'managed',
);
const lifecycle = JSON.parse(
await readFile(join(clientDataRoot, 'runtime-host-local-service.json'), 'utf8'),
) as { readonly state: string; readonly deploymentId: string };
assert.equal(lifecycle.state, 'managed');
assert.equal((lifecycle as { serviceId?: string }).serviceId, 'a'.repeat(64));
assert.equal(lifecycle.deploymentId, deploymentId);
});

test('revokes the one Local sharing authority without changing peer connectivity', async (t) => {
Expand Down Expand Up @@ -192,14 +204,12 @@ test('an interrupted Local Host handoff converges to its exact managed service',
const clientDataRoot = join(base, 'client');
const rootPath = join(clientDataRoot, 'workspaces', 'default');
const rootId = 'a'.repeat(64);
const serviceId = resolveRuntimeHostManagedServiceId(clientDataRoot);
await mkdir(rootPath, { recursive: true });
await writeFile(
join(clientDataRoot, 'runtime-host-local-service.json'),
`${JSON.stringify({
schemaVersion: 1,
state: 'handoff',
serviceId,
rootPath,
rootId,
coordinationRelays: [],
Expand All @@ -225,10 +235,11 @@ test('an interrupted Local Host handoff converges to its exact managed service',
async runSetup() {
setupCalls += 1;
return {
serviceId,
serviceId: rootId,
operatorPath: join(base, 'operator'),
rootPath,
rootId,
deploymentId: '22222222-2222-4222-8222-222222222222',
credential: 'unused-pending-credential',
directPeer: {
peerId: '12D3KooWpeer',
Expand Down Expand Up @@ -268,6 +279,7 @@ test('startup replays the persisted peer intent instead of gating recovery on st
operatorPath: join(clientDataRoot, 'operator'),
rootPath,
rootId,
deploymentId: RECOVERY_DEPLOYMENT_ID,
peerEnabled: true,
coordinationRelays: ['/dns4/discovery.example/udp/443/quic-v1'],
allowInterruptActiveTasks: false,
Expand Down Expand Up @@ -401,10 +413,12 @@ test('startup completes an exact persisted uninstall intent after Desktop interr
operatorPath: join(base, 'operator'),
rootPath,
rootId,
deploymentId: RECOVERY_DEPLOYMENT_ID,
allowInterruptActiveTasks: false,
})}\n`,
);
const actions: string[] = [];
const cleanupPhases: boolean[] = [];
const service = createDesktopLocalRuntimeHostRemoteAccess({
ipcMain: { handle() {}, removeHandler() {} },
clientDataRoot,
Expand Down Expand Up @@ -433,16 +447,18 @@ test('startup completes an exact persisted uninstall intent after Desktop interr
service: { state: 'not_installed' },
};
},
async cleanupManagedDeployment() {
async cleanupManagedDeployment(input: { readonly finalize?: boolean }) {
actions.push('cleanup');
cleanupPhases.push(input.finalize ?? false);
},
async close() {},
} as unknown as ReturnType<typeof createDesktopRuntimeHostLocalOperator>,
});
t.after(() => service.close());

await service.recover();
assert.deepEqual(actions, ['uninstall', 'cleanup']);
assert.deepEqual(actions, ['uninstall', 'cleanup', 'cleanup']);
assert.deepEqual(cleanupPhases, [false, true]);
await assert.rejects(readFile(join(clientDataRoot, 'runtime-host-local-service.json'), 'utf8'), {
code: 'ENOENT',
});
Expand All @@ -463,6 +479,7 @@ test('startup resumes deployment cleanup without repeating a completed uninstall
operatorPath: join(base, 'operator'),
rootPath,
rootId: 'a'.repeat(64),
deploymentId: RECOVERY_DEPLOYMENT_ID,
allowInterruptActiveTasks: false,
})}\n`,
);
Expand Down Expand Up @@ -508,6 +525,7 @@ async function writeManagedLifecycle(
operatorPath: join(clientDataRoot, 'operator'),
rootPath,
rootId,
deploymentId: RECOVERY_DEPLOYMENT_ID,
})}\n`,
);
}
Expand Down
117 changes: 103 additions & 14 deletions apps/desktop/src/main/__tests__/runtime-host-managed-services.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import assert from "node:assert/strict";
import { mkdtemp, readFile, rm } from "node:fs/promises";
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, test } from "node:test";
Expand All @@ -27,6 +27,10 @@ import {
createDesktopRuntimeHostManagedServiceStore,
findDesktopRuntimeHostManagedServiceBinding,
} from "../runtime-host-managed-services.js";
import {
createDesktopRuntimeHostProfileService,
resolveDesktopRuntimeHostStartup,
} from "../runtime-host-profile-service.js";

const roots: string[] = [];
const profile = {
Expand All @@ -46,24 +50,75 @@ const service = {
rootPath: "/srv/maka",
operatorPath: "/home/operator/.local/share/maka/operator",
};
const deploymentId = "11111111-1111-4111-8111-111111111111";
const deployedService = {
deployment: { id: service.id, rootPath: service.rootPath, deploymentId },
control: { kind: "ssh_operator" as const, operatorPath: service.operatorPath },
};

afterEach(async () => {
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true })));
await Promise.all(
roots.splice(0).map((root) => rm(root, { recursive: true })),
);
});

test("keeps Desktop service bindings outside the shared profile catalog", async () => {
const root = await mkdtemp(join(tmpdir(), "maka-managed-host-services-"));
roots.push(root);
const catalog = createClientRuntimeHostProfileCatalog(root);
const legacyPath = join(root, "runtime-host-managed-services.json");
const legacyDocument = `${JSON.stringify({
schemaVersion: 1,
bindings: [{ profile, service, state: "uninstalling" }],
})}\n`;
await writeFile(
legacyPath,
legacyDocument,
);
const managedServices = createDesktopRuntimeHostManagedServiceStore(root);
const concurrentStore = createDesktopRuntimeHostManagedServiceStore(root);
await catalog.create(profile, "secret");

assert.equal((await managedServices.read()).bindings[0]?.deployment.id, service.id);
await assert.rejects(readFile(legacyPath, "utf8"), {
code: "ENOENT",
});
await writeFile(legacyPath, legacyDocument);
await managedServices.read();
await assert.rejects(readFile(legacyPath, "utf8"), { code: "ENOENT" });

const profileService = createDesktopRuntimeHostProfileService({
clientDataRoot: root,
startup: await resolveDesktopRuntimeHostStartup(root, { catalog }),
catalog,
managedServices,
states: () => [],
enable: async () => undefined,
disable: async () => undefined,
setDefault: () => undefined,
finalizePairing: async () => undefined,
});
const legacyUninstall = await profileService.resolveManagedService(profile.id);
assert.ok(legacyUninstall);
assert.equal(legacyUninstall.deployment.deploymentId, undefined);
assert.equal(legacyUninstall.state, "uninstalling");
assert.equal(
(await profileService.markManagedServiceUninstalling(legacyUninstall)).state,
"uninstalling",
);

await Promise.all([
managedServices.save(profile, service),
managedServices.save(profile, deployedService),
concurrentStore.save(
{ ...profile, id: "lab", rootId: "d".repeat(64) },
{ ...service, id: "e".repeat(64) },
{
...deployedService,
deployment: {
...deployedService.deployment,
id: "e".repeat(64),
deploymentId: "22222222-2222-4222-8222-222222222222",
},
},
),
]);

Expand All @@ -72,28 +127,62 @@ test("keeps Desktop service bindings outside the shared profile catalog", async
/managedService/u,
);
assert.deepEqual(
findDesktopRuntimeHostManagedServiceBinding(await managedServices.read(), profile),
{ profile: { ...profile, transport: { ...profile.transport } }, service, state: "active" },
findDesktopRuntimeHostManagedServiceBinding(
await managedServices.read(),
profile,
),
{
profile: { ...profile, transport: { ...profile.transport } },
deployment: { id: service.id, rootPath: service.rootPath, deploymentId },
control: { kind: "ssh_operator", operatorPath: service.operatorPath },
state: "active",
},
);
assert.equal((await managedServices.read()).bindings.length, 2);
assert.equal(
findDesktopRuntimeHostManagedServiceBinding(await managedServices.read(), {
...profile,
transport: { ...profile.transport, destination: "operator@new.example.com" },
transport: {
...profile.transport,
destination: "operator@new.example.com",
},
}),
undefined,
);
assert.equal(await managedServices.markUninstallingIfCurrent(profile, service), true);
const binding = findDesktopRuntimeHostManagedServiceBinding(
await managedServices.read(),
profile,
);
assert.ok(binding);
assert.equal(await managedServices.markUninstallingIfCurrent(binding), true);
assert.equal(
findDesktopRuntimeHostManagedServiceBinding(await managedServices.read(), profile)?.state,
findDesktopRuntimeHostManagedServiceBinding(
await managedServices.read(),
profile,
)?.state,
"uninstalling",
);
assert.equal(await managedServices.removeCleanupPendingIfCurrent(profile, service), false);
assert.equal(await managedServices.markCleanupPendingIfCurrent(profile, service), true);
assert.equal(
findDesktopRuntimeHostManagedServiceBinding(await managedServices.read(), profile)?.state,
await managedServices.removeCleanupPendingIfCurrent(binding),
false,
);
assert.equal(
await managedServices.markCleanupPendingIfCurrent(binding),
true,
);
assert.equal(
findDesktopRuntimeHostManagedServiceBinding(
await managedServices.read(),
profile,
)?.state,
"cleanup_pending",
);
assert.equal(await managedServices.markUninstallingIfCurrent(profile, service), false);
assert.equal(await managedServices.removeCleanupPendingIfCurrent(profile, service), true);
assert.equal(
await managedServices.markUninstallingIfCurrent(binding),
false,
);
assert.equal(
await managedServices.removeCleanupPendingIfCurrent(binding),
true,
);
});
Loading
Loading