9670d0a86a
Scan History: - Proxmox is now a first-class scan kind (badge, filter chip, Server icon, completion toast) instead of being mislabeled as an IP scan. - A done run carrying a non-fatal advisory renders amber (info) with a warning toast, distinct from red failures. Import diagnostics: - test-connection probes /access/permissions and warns when the API token has no ACL (VMs/LXC would be invisible) — points at the PVEAuditor grant. - import surfaces an advisory when hosts import but no guests are visible (privilege-separated token whose rights are the intersection with the user), rather than a silent "done". Node style: - Proxmox container mode is now opt-in (container_mode === true), matching the rest of the codebase (App.tsx nesting logic). Imported proxmox nodes leave the flag unset and render like a manually-created node instead of an empty group container. Cluster edges: - Hosts from one import are chained with 'cluster' edges via left/right handles, distinct from the vertical host->guest 'virtual' edges. Wired for both the direct "Add to Canvas" path and the pending -> approve path (host<->host proxmox_cluster links, resolved to cluster edges on approve; cluster hosts get left/right handles). Tests added on both sides. ha-relevant: maybe
46 lines
1.6 KiB
TypeScript
46 lines
1.6 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import {
|
|
buildProxmoxClusterEdges,
|
|
isProxmoxCluster,
|
|
CLUSTER_SOURCE_HANDLE,
|
|
CLUSTER_TARGET_HANDLE,
|
|
} from '../clusterEdges'
|
|
import type { ProxmoxNode } from '../types'
|
|
|
|
function host(id: string): ProxmoxNode {
|
|
return { id, label: id, type: 'proxmox', ieee_address: id, status: 'online' }
|
|
}
|
|
function guest(id: string, type: 'vm' | 'lxc' = 'vm'): ProxmoxNode {
|
|
return { id, label: id, type, ieee_address: id, status: 'online' }
|
|
}
|
|
|
|
describe('buildProxmoxClusterEdges', () => {
|
|
it('chains multiple hosts left→right, ignoring guests', () => {
|
|
const nodes = [host('pve-a'), guest('vm-1'), host('pve-b'), host('pve-c'), guest('ct-1', 'lxc')]
|
|
const edges = buildProxmoxClusterEdges(nodes)
|
|
expect(edges.map((e) => [e.source, e.target])).toEqual([
|
|
['pve-a', 'pve-b'],
|
|
['pve-b', 'pve-c'],
|
|
])
|
|
// Endpoints use the left/right handles.
|
|
for (const e of edges) {
|
|
expect(e.sourceHandle).toBe(CLUSTER_SOURCE_HANDLE)
|
|
expect(e.targetHandle).toBe(CLUSTER_TARGET_HANDLE)
|
|
}
|
|
})
|
|
|
|
it('returns no edges for a single host', () => {
|
|
expect(buildProxmoxClusterEdges([host('pve-a'), guest('vm-1')])).toEqual([])
|
|
})
|
|
|
|
it('returns no edges when there are no hosts', () => {
|
|
expect(buildProxmoxClusterEdges([guest('vm-1'), guest('ct-1', 'lxc')])).toEqual([])
|
|
})
|
|
|
|
it('isProxmoxCluster is true only with 2+ hosts', () => {
|
|
expect(isProxmoxCluster([host('a')])).toBe(false)
|
|
expect(isProxmoxCluster([host('a'), host('b')])).toBe(true)
|
|
expect(isProxmoxCluster([host('a'), guest('vm-1')])).toBe(false)
|
|
})
|
|
})
|