eeadeef664
CI / checks (pull_request) Successful in 26m59s
Console Home counted every available service through the generic resource list, but MSK and MSK Connect are available through their own pre-SPI pages with no adapter behind /resources, so each answered 501 and the Resources tile read "Resource load failed". Service descriptors now say whether the generic list serves them (listable, true when an adapter is registered), and Console Home counts only those; the MSK cards still link to their pages.
103 lines
5.5 KiB
TypeScript
103 lines
5.5 KiB
TypeScript
import {describe, expect, test} from 'bun:test'
|
|
import type {CloudProvider, CloudServiceDescriptor, CloudStatus} from '../cloud-spi/types'
|
|
import {runtimeDiagnostics} from './runtimeDiagnostics'
|
|
|
|
const STARTED_AT = new Date('2026-10-23T08:00:00.000Z')
|
|
const NOW = new Date('2026-10-23T10:30:15.000Z')
|
|
|
|
function descriptor(service: CloudServiceDescriptor['service'], displayName: string, availability: CloudServiceDescriptor['availability'] = 'available'): CloudServiceDescriptor {
|
|
return {cloud: 'aws', service, displayName, availability, route: `/cloud-explorer/aws/${service}`, iconKey: service, group: 'Compute', order: 1, listable: availability === 'available'}
|
|
}
|
|
|
|
function proxy(status: Partial<CloudStatus> = {}, descriptors: CloudServiceDescriptor[] = []) {
|
|
return {
|
|
status: async (cloud: CloudProvider) => ({
|
|
cloud, adapterRegistered: true, runtime: 'reachable', endpoint: 'http://floci:4566', checkedAt: NOW.toISOString(), error: null,
|
|
services: [{cloud, service: 'storage', adapterRegistered: true, runtime: 'reachable', endpoint: 'http://floci:4566', checkedAt: NOW.toISOString(), latencyMs: 4, error: null, errorCode: null}],
|
|
...status,
|
|
}) as CloudStatus,
|
|
services: () => descriptors,
|
|
}
|
|
}
|
|
|
|
function runtime(responses: Record<string, unknown>): typeof fetch {
|
|
return (async (input: string | URL | Request) => {
|
|
const path = new URL(String(input instanceof Request ? input.url : input)).pathname
|
|
return path in responses ? Response.json(responses[path]) : new Response('not found', {status: 404})
|
|
}) as unknown as typeof fetch
|
|
}
|
|
|
|
const fixed = {now: () => NOW, startedAt: STARTED_AT, authMode: 'oidc' as const, activeSessions: () => 2}
|
|
|
|
describe('runtimeDiagnostics', () => {
|
|
test('reports the runtime version, every emulated service and its console pages', async () => {
|
|
const report = await runtimeDiagnostics('aws', proxy({}, [
|
|
descriptor('storage', 'S3'),
|
|
descriptor('loadbalancing', 'Load Balancers'),
|
|
descriptor('targetgroups', 'Target Groups'),
|
|
descriptor('scheduler', 'Scheduler', 'coming_soon'),
|
|
]), {
|
|
...fixed,
|
|
fetch: runtime({'/_floci/health': {version: '1.9.0', edition: 'compat', services: {s3: 'running', elasticloadbalancing: 'running', route53: 'running', scheduler: 'stopped'}}}),
|
|
})
|
|
|
|
expect(report.runtime).toMatchObject({status: 'reachable', endpoint: 'http://floci:4566', version: '1.9.0', edition: 'compat', error: null})
|
|
expect(report.runtime.latencyMs).toBeNumber()
|
|
expect(report.emulatedServices).toEqual([
|
|
{name: 'elasticloadbalancing', state: 'running', consolePages: [
|
|
{service: 'loadbalancing', displayName: 'Load Balancers', route: '/cloud-explorer/aws/loadbalancing'},
|
|
{service: 'targetgroups', displayName: 'Target Groups', route: '/cloud-explorer/aws/targetgroups'},
|
|
]},
|
|
{name: 'route53', state: 'running', consolePages: []},
|
|
{name: 's3', state: 'running', consolePages: [{service: 'storage', displayName: 'S3', route: '/cloud-explorer/aws/storage'}]},
|
|
{name: 'scheduler', state: 'stopped', consolePages: []},
|
|
])
|
|
expect(report.consoleServices).toHaveLength(1)
|
|
})
|
|
|
|
test('lists the containers the runtime started for EC2 instances', async () => {
|
|
const report = await runtimeDiagnostics('aws', proxy(), {
|
|
...fixed,
|
|
fetch: runtime({'/_floci/diagnose': {ec2: {instances: [
|
|
{instanceId: 'i-0abc', containerStatus: 'running', sshHost: 'localhost', sshPort: 2201},
|
|
{instanceId: 'i-0def', containerStatus: 'stopped'},
|
|
{containerStatus: 'running'},
|
|
]}}}),
|
|
})
|
|
|
|
expect(report.containers).toEqual([
|
|
{kind: 'ec2-instance', resourceId: 'i-0abc', status: 'running', sshHost: 'localhost', sshPort: 2201},
|
|
{kind: 'ec2-instance', resourceId: 'i-0def', status: 'stopped', sshHost: null, sshPort: null},
|
|
])
|
|
})
|
|
|
|
test('still returns a partial report when the runtime is down', async () => {
|
|
const report = await runtimeDiagnostics('aws', proxy({runtime: 'unavailable', error: 'Cannot reach Floci core at http://floci:4566', services: []}), {
|
|
...fixed,
|
|
fetch: (async () => { throw new TypeError('fetch failed') }) as unknown as typeof fetch,
|
|
})
|
|
|
|
expect(report.runtime).toEqual({status: 'unavailable', endpoint: 'http://floci:4566', latencyMs: null, error: 'Cannot reach Floci core at http://floci:4566', version: null, edition: null})
|
|
expect(report.emulatedServices).toBeNull()
|
|
expect(report.containers).toBeNull()
|
|
})
|
|
|
|
test('does not query Floci core endpoints for other clouds', async () => {
|
|
const requested: string[] = []
|
|
const report = await runtimeDiagnostics('azure', proxy(), {
|
|
...fixed,
|
|
fetch: (async (input: string | URL | Request) => { requested.push(String(input)); return Response.json({}) }) as unknown as typeof fetch,
|
|
})
|
|
|
|
expect(requested).toEqual([])
|
|
expect(report.emulatedServices).toBeNull()
|
|
})
|
|
|
|
test('describes the console process itself', async () => {
|
|
const report = await runtimeDiagnostics('aws', proxy(), {...fixed, fetch: runtime({})})
|
|
|
|
expect(report.checkedAt).toBe('2026-10-23T10:30:15.000Z')
|
|
expect(report.console).toEqual({startedAt: '2026-10-23T08:00:00.000Z', uptimeSeconds: 9015, authMode: 'oidc', activeSessions: 2})
|
|
})
|
|
})
|