Files
netbird/client/ui/frontend/src/lib/mock.ts

416 lines
14 KiB
TypeScript

import { Network, PeerStatus } from "@bindings/services/models.js";
// Flip to true to override the live daemon data in the Peers / Resources /
// Exit Nodes tabs with the hand-crafted fixtures below. The fixtures are
// designed to surface overflow / truncation bugs (very long FQDNs, ICE
// endpoints, domain lists, network ids) and exercise the three connection
// states + relayed / P2P / Rosenpass variants.
export const MOCK_ENABLED = false;
// Replace `real` with `mock` when MOCK_ENABLED. Pulled out so call sites read
// as "use the live X, or the mock if enabled" without per-site if/else noise.
export const mockOr = <T>(real: T, mock: T): T => (MOCK_ENABLED ? mock : real);
const SECONDS = (s: number) => Math.floor(Date.now() / 1000) - s;
const MINUTES = (m: number) => SECONDS(m * 60);
const HOURS = (h: number) => MINUTES(h * 60);
const DAYS = (d: number) => HOURS(d * 24);
export const mockPeers: PeerStatus[] = [
// Kitchen-sink peer — every optional field populated at the same time so
// the detail panel renders every Row (latency + bytes + handshake + ICE
// local/remote + relay + networks + rosenpass + pubkey). Useful for
// eyeballing layout at maximum density.
new PeerStatus({
ip: "100.64.0.1",
pubKey: "MockKeyEverythingMaxedOutForLayoutTestingAA=",
connStatus: "Connected",
connStatusUpdateUnix: SECONDS(4),
relayed: true,
localIceCandidateType: "prflx",
remoteIceCandidateType: "relay",
localIceCandidateEndpoint: "[2001:db8:abcd:0012:0000:0000:0000:0001]:51820",
remoteIceCandidateEndpoint: "relay-eu-central-1.netbird.io:443",
fqdn: "everything-maxed-out-kitchen-sink-peer-with-long-name.subdomain.dev.example-company.netbird.cloud",
bytesRx: 87_654_321_098,
bytesTx: 43_210_987_654,
latencyMs: 213,
relayAddress:
"rels://relay-eu-central-1.netbird.io:443/very/long/relay/path/segment/with/many/parts",
lastHandshakeUnix: SECONDS(3),
rosenpassEnabled: true,
networks: [
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"100.100.0.0/16",
"10.50.50.0/24",
"2001:db8::/32",
"203.0.113.0/24",
"198.51.100.0/24",
],
}),
new PeerStatus({
ip: "100.64.0.2",
pubKey: "MockKeyAlpha000000000000000000000000000000=",
connStatus: "Connected",
connStatusUpdateUnix: MINUTES(7),
relayed: false,
localIceCandidateType: "host",
remoteIceCandidateType: "srflx",
localIceCandidateEndpoint: "192.168.1.10:51820",
remoteIceCandidateEndpoint: "203.0.113.42:51820",
fqdn: "alpha.netbird.cloud",
bytesRx: 12_345_678,
bytesTx: 9_876_543,
latencyMs: 18,
relayAddress: "",
lastHandshakeUnix: SECONDS(12),
rosenpassEnabled: false,
networks: ["10.0.0.0/24"],
}),
new PeerStatus({
ip: "100.64.0.3",
pubKey: "MockKeyLongFqdn000000000000000000000000000=",
connStatus: "Connected",
connStatusUpdateUnix: HOURS(2),
relayed: false,
localIceCandidateType: "srflx",
remoteIceCandidateType: "srflx",
localIceCandidateEndpoint: "198.51.100.7:41234",
remoteIceCandidateEndpoint: "203.0.113.99:51820",
fqdn: "very-long-hostname-with-many-segments-to-test-overflow-handling.subdomain.example-company.netbird.cloud",
bytesRx: 4_500_000_000,
bytesTx: 1_200_000_000,
latencyMs: 87,
relayAddress: "",
lastHandshakeUnix: SECONDS(45),
rosenpassEnabled: false,
networks: [],
}),
new PeerStatus({
ip: "100.64.0.4",
pubKey: "MockKeyConnecting00000000000000000000000000=",
connStatus: "Connecting",
connStatusUpdateUnix: SECONDS(3),
relayed: false,
localIceCandidateType: "",
remoteIceCandidateType: "",
localIceCandidateEndpoint: "",
remoteIceCandidateEndpoint: "",
fqdn: "edge-server.netbird.cloud",
bytesRx: 0,
bytesTx: 0,
latencyMs: 0,
relayAddress: "",
lastHandshakeUnix: 0,
rosenpassEnabled: false,
networks: [],
}),
new PeerStatus({
ip: "100.64.0.5",
pubKey: "MockKeyOfflineOld0000000000000000000000000=",
connStatus: "Idle",
connStatusUpdateUnix: DAYS(4),
relayed: false,
localIceCandidateType: "",
remoteIceCandidateType: "",
localIceCandidateEndpoint: "",
remoteIceCandidateEndpoint: "",
fqdn: "old-peer-offline.netbird.cloud",
bytesRx: 0,
bytesTx: 0,
latencyMs: 0,
relayAddress: "",
lastHandshakeUnix: DAYS(4),
rosenpassEnabled: false,
networks: [],
}),
new PeerStatus({
ip: "100.64.0.6",
pubKey: "MockKeyRelayed00000000000000000000000000000=",
connStatus: "Connected",
connStatusUpdateUnix: MINUTES(30),
relayed: true,
localIceCandidateType: "relay",
remoteIceCandidateType: "relay",
localIceCandidateEndpoint: "relay-eu-central-1.netbird.io:443",
remoteIceCandidateEndpoint: "relay-eu-central-1.netbird.io:443",
fqdn: "relayed-host-behind-strict-nat.corp.example.com",
bytesRx: 250_000,
bytesTx: 180_000,
latencyMs: 142,
relayAddress: "rels://relay-eu-central-1.netbird.io:443/very/long/relay/path/segment",
lastHandshakeUnix: SECONDS(8),
rosenpassEnabled: false,
networks: ["10.10.0.0/16", "192.168.50.0/24"],
}),
new PeerStatus({
ip: "100.64.0.7",
pubKey: "MockKeyIPv6000000000000000000000000000000000=",
connStatus: "Connected",
connStatusUpdateUnix: HOURS(1),
relayed: false,
localIceCandidateType: "host",
remoteIceCandidateType: "host",
localIceCandidateEndpoint: "[2001:db8:85a3:0000:0000:8a2e:0370:7334]:51820",
remoteIceCandidateEndpoint: "[fe80::1ff:fe23:4567:890a]:51820",
fqdn: "ipv6-only-host.netbird.cloud",
bytesRx: 999_999,
bytesTx: 1_500_000,
latencyMs: 64,
relayAddress: "",
lastHandshakeUnix: SECONDS(22),
rosenpassEnabled: false,
networks: [],
}),
new PeerStatus({
ip: "100.64.0.8",
pubKey: "MockKeyRosenpass0000000000000000000000000000=",
connStatus: "Connected",
connStatusUpdateUnix: MINUTES(15),
relayed: false,
localIceCandidateType: "prflx",
remoteIceCandidateType: "prflx",
localIceCandidateEndpoint: "10.0.0.50:51820",
remoteIceCandidateEndpoint: "203.0.113.200:51820",
fqdn: "rosenpass-secure.netbird.cloud",
bytesRx: 50_000,
bytesTx: 50_000,
latencyMs: 24,
relayAddress: "",
lastHandshakeUnix: SECONDS(5),
rosenpassEnabled: true,
networks: [],
}),
new PeerStatus({
ip: "100.64.0.9",
pubKey: "MockKeyMultiNet00000000000000000000000000000=",
connStatus: "Connected",
connStatusUpdateUnix: HOURS(5),
relayed: false,
localIceCandidateType: "host",
remoteIceCandidateType: "srflx",
localIceCandidateEndpoint: "10.0.0.51:51820",
remoteIceCandidateEndpoint: "203.0.113.201:51820",
fqdn: "multi-network-router.netbird.cloud",
bytesRx: 12_000_000_000,
bytesTx: 8_000_000_000,
latencyMs: 31,
relayAddress: "",
lastHandshakeUnix: SECONDS(2),
rosenpassEnabled: false,
networks: [
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"100.100.0.0/16",
"10.50.50.0/24",
"2001:db8::/32",
],
}),
new PeerStatus({
ip: "100.64.0.10",
pubKey: "MockKeyA000000000000000000000000000000000000=",
connStatus: "Idle",
connStatusUpdateUnix: MINUTES(45),
relayed: false,
localIceCandidateType: "",
remoteIceCandidateType: "",
localIceCandidateEndpoint: "",
remoteIceCandidateEndpoint: "",
fqdn: "a.nb",
bytesRx: 0,
bytesTx: 0,
latencyMs: 0,
relayAddress: "",
lastHandshakeUnix: MINUTES(45),
rosenpassEnabled: false,
networks: [],
}),
// IPv6-NetBird-IP peer: the daemon assigns a v6 ULA inside fd00::/8 when
// running on a v6-native overlay. Exercises the row layout when the IP
// column is wide.
new PeerStatus({
ip: "fd00:1234:5678:abcd::42",
pubKey: "MockKeyV6Native0000000000000000000000000000=",
connStatus: "Connected",
connStatusUpdateUnix: MINUTES(20),
relayed: false,
localIceCandidateType: "host",
remoteIceCandidateType: "host",
localIceCandidateEndpoint: "[2001:db8:cafe:0001::10]:51820",
remoteIceCandidateEndpoint: "[2001:db8:cafe:0002::20]:51820",
fqdn: "ipv6-overlay-peer.netbird.cloud",
bytesRx: 800_000_000,
bytesTx: 950_000_000,
latencyMs: 41,
relayAddress: "",
lastHandshakeUnix: SECONDS(7),
rosenpassEnabled: false,
networks: ["2001:db8:1::/48", "2001:db8:2::/48", "fc00:dead:beef::/48"],
}),
// Dual-stack peer with mixed IPv4 / IPv6 ICE endpoints to test rows
// where local and remote columns differ in width.
new PeerStatus({
ip: "100.64.0.11",
pubKey: "MockKeyDualStack0000000000000000000000000000=",
connStatus: "Connected",
connStatusUpdateUnix: MINUTES(10),
relayed: false,
localIceCandidateType: "host",
remoteIceCandidateType: "srflx",
localIceCandidateEndpoint: "10.0.0.99:51820",
remoteIceCandidateEndpoint: "[2606:4700:4700:0000:0000:0000:0000:1111]:51820",
fqdn: "dual-stack.netbird.cloud",
bytesRx: 320_000_000,
bytesTx: 410_000_000,
latencyMs: 28,
relayAddress: "",
lastHandshakeUnix: SECONDS(14),
rosenpassEnabled: false,
networks: ["10.20.30.0/24", "2001:db8:beef::/48"],
}),
];
// Resources / routed networks. Mixes the three resource types the UI knows
// about (host = /32 or /128, subnet, domain) plus a deliberately overlapping
// pair to exercise the "overlapping" badge in NetworkFilters.
export const mockNetworkRoutes: Network[] = [
new Network({
id: "host-jenkins",
range: "10.0.0.1/32",
selected: true,
domains: [],
resolvedIps: {},
}),
new Network({
id: "subnet-corp-lan",
range: "192.168.1.0/24",
selected: true,
domains: [],
resolvedIps: {},
}),
new Network({
id: "subnet-wide-internal",
range: "10.0.0.0/8",
selected: false,
domains: [],
resolvedIps: {},
}),
new Network({
id: "subnet-overlap-a",
range: "172.16.0.0/16",
selected: true,
domains: [],
resolvedIps: {},
}),
new Network({
id: "subnet-overlap-b",
range: "172.16.0.0/16",
selected: false,
domains: [],
resolvedIps: {},
}),
new Network({
id: "dns-example",
range: "invalid Prefix",
selected: true,
domains: ["example.com"],
resolvedIps: { "example.com": ["93.184.216.34"] },
}),
new Network({
id: "dns-very-long-internal-domain-with-many-segments",
range: "invalid Prefix",
selected: false,
domains: [
"very-long-internal-service-name.dev.subdomain.example-company.internal",
"another-long-domain-for-overflow-testing.example-company.internal",
"third-long-domain-in-the-list.example-company.internal",
],
resolvedIps: {
"very-long-internal-service-name.dev.subdomain.example-company.internal": [
"10.20.30.40",
"10.20.30.41",
],
},
}),
new Network({
id: "ipv6-host",
range: "2001:db8::1/128",
selected: false,
domains: [],
resolvedIps: {},
}),
new Network({
id: "ipv6-subnet-corp",
range: "2001:db8:abcd::/48",
selected: true,
domains: [],
resolvedIps: {},
}),
new Network({
id: "ipv6-subnet-large",
range: "fc00:dead:beef::/32",
selected: false,
domains: [],
resolvedIps: {},
}),
new Network({
id: "dns-dual-stack",
range: "invalid Prefix",
selected: true,
domains: ["dual-stack.internal.example.com"],
resolvedIps: {
"dual-stack.internal.example.com": [
"10.20.30.40",
"10.20.30.41",
"2001:db8:abcd::40",
"2001:db8:abcd::41",
],
},
}),
new Network({
id: "dns-ipv6-only",
range: "invalid Prefix",
selected: false,
domains: ["ipv6-only-service.example.com"],
resolvedIps: {
"ipv6-only-service.example.com": ["2606:4700:4700::1111", "2606:4700:4700::1001"],
},
}),
];
// Exit nodes are radio-style (mutually exclusive in the UI). Include one
// selected and one absurdly-long-id to test row truncation.
export const mockExitNodes: Network[] = [
new Network({
id: "us-east-1",
range: "0.0.0.0/0",
selected: false,
domains: [],
resolvedIps: {},
}),
new Network({
id: "eu-central-frankfurt-primary",
range: "0.0.0.0/0",
selected: true,
domains: [],
resolvedIps: {},
}),
new Network({
id: "very-long-exit-node-region-identifier-with-multiple-segments-and-numbers-12345-test",
range: "0.0.0.0/0",
selected: false,
domains: [],
resolvedIps: {},
}),
new Network({
id: "ap-southeast-2",
range: "0.0.0.0/0",
selected: false,
domains: [],
resolvedIps: {},
}),
];