feat: add FPTN section action UI, config fields, dashboard status, and diagnostics
- Add FPTN to ROUTING_ACTIONS, actionProvidersAvailabilityState, isFptnInstalledForUi() - Add FPTN action option label (FPTN) in getActionOptionLabel and getRuleActionDisplayValue - Add FPTN to populateActionOptionValues (guarded by isFptnInstalledForUi()) - Add FPTN section config fields: access_token (required), sni, bypass_method, preferred_server - Add fptn to ACTION_COLORS (#e74c3c) - Add GetFptnStatus type, GET_FPTN_STATUS method, getFptnStatus() shell method - Add fptn to dashboard: getDashboardSections, renderSections, getServiceStatus handler - Add get_fptn_status CLI dispatch and get-fptn-status handler in diagnostics/runtime.uc - Add FPTN unit test in getDashboardSections.test.ts - Update translation calls index (locales/calls.json)
This commit is contained in:
+1736
-1683
File diff suppressed because it is too large
Load Diff
@@ -404,6 +404,7 @@ const ACTION_DISPLAY_NAMES: Record<string, string> = {
|
||||
sudoku: 'Sudoku',
|
||||
masque: 'MASQUE',
|
||||
openvpn: 'OpenVPN',
|
||||
fptn: 'FPTN',
|
||||
};
|
||||
|
||||
function isConnectionAction(action?: string) {
|
||||
@@ -417,7 +418,9 @@ function isConnectionAction(action?: string) {
|
||||
function isServiceAction(action?: string) {
|
||||
return Boolean(
|
||||
action &&
|
||||
['zapret', 'zapret2', 'byedpi', 'wdtt', 'olcrtc'].includes(action),
|
||||
['zapret', 'zapret2', 'byedpi', 'wdtt', 'olcrtc', 'fptn'].includes(
|
||||
action,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1606,7 +1609,7 @@ export async function getDashboardSections(
|
||||
>();
|
||||
|
||||
const getServiceStatus = (
|
||||
serviceType: 'zapret' | 'zapret2' | 'byedpi' | 'wdtt' | 'olcrtc',
|
||||
serviceType: 'zapret' | 'zapret2' | 'byedpi' | 'wdtt' | 'olcrtc' | 'fptn',
|
||||
) => {
|
||||
if (!serviceStatusCache.has(serviceType)) {
|
||||
serviceStatusCache.set(
|
||||
@@ -1693,6 +1696,23 @@ export async function getDashboardSections(
|
||||
statusMessage: s.status_message,
|
||||
};
|
||||
}
|
||||
} else if (serviceType === 'fptn') {
|
||||
const result = await TachyonShellMethods.getFptnStatus();
|
||||
if (result.success && result.data) {
|
||||
const s = result.data;
|
||||
return {
|
||||
serviceType: 'fptn',
|
||||
configured: Boolean(s.configured),
|
||||
ready: Boolean(s.ready),
|
||||
conflict: false,
|
||||
runningProcesses: s.service_running ? 1 : 0,
|
||||
expectedProcesses: s.configured ? 1 : 0,
|
||||
restartCount: 0,
|
||||
unstable: false,
|
||||
statusMessage:
|
||||
s.status_message || (s.ready ? _('Running') : _('Stopped')),
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (_error) {
|
||||
// Status fetch failed — show section without status
|
||||
@@ -1829,7 +1849,8 @@ export async function getDashboardSections(
|
||||
}
|
||||
|
||||
if (isServiceAction(sectionAction)) {
|
||||
const serviceType = sectionAction as 'zapret' | 'zapret2' | 'byedpi';
|
||||
const serviceType =
|
||||
sectionAction as Tachyon.ServiceStatus['serviceType'];
|
||||
const serviceStatus = await getServiceStatus(serviceType);
|
||||
|
||||
const statusLabel = serviceStatus
|
||||
|
||||
@@ -3,6 +3,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
const mocks = vi.hoisted(() => ({
|
||||
getConfigSections: vi.fn(),
|
||||
getClashApiProxies: vi.fn(),
|
||||
getFptnStatus: vi.fn(),
|
||||
canUseDirectClashApi: vi.fn(),
|
||||
fsRead: vi.fn(),
|
||||
}));
|
||||
@@ -14,6 +15,7 @@ vi.mock('../getConfigSections', () => ({
|
||||
vi.mock('../../shell', () => ({
|
||||
TachyonShellMethods: {
|
||||
getClashApiProxies: mocks.getClashApiProxies,
|
||||
getFptnStatus: mocks.getFptnStatus,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -1306,4 +1308,36 @@ describe('getDashboardSections', () => {
|
||||
expect(outbound?.prefix).toBe('Geodema Network');
|
||||
expect(outbound?.displayName).toBe('🇫🇷 France');
|
||||
});
|
||||
|
||||
it('returns FPTN service section with running status on dashboard', async () => {
|
||||
mocks.getConfigSections.mockResolvedValue([
|
||||
{
|
||||
'.name': 'fptn_sec',
|
||||
'.type': 'section',
|
||||
enabled: '1',
|
||||
action: 'fptn',
|
||||
access_token: 'test_token',
|
||||
},
|
||||
]);
|
||||
mocks.getFptnStatus.mockResolvedValue({
|
||||
success: true,
|
||||
data: {
|
||||
installed: true,
|
||||
configured: true,
|
||||
service_running: true,
|
||||
ready: true,
|
||||
status_message: 'FPTN is running',
|
||||
},
|
||||
});
|
||||
|
||||
const result = await getDashboardSections();
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data).toHaveLength(1);
|
||||
expect(result.data[0].sectionName).toBe('fptn_sec');
|
||||
expect(result.data[0].action).toBe('fptn');
|
||||
expect(result.data[0].serviceStatus?.serviceType).toBe('fptn');
|
||||
expect(result.data[0].serviceStatus?.ready).toBe(true);
|
||||
expect(result.data[0].outbounds[0].displayName).toBe('Running');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -330,6 +330,13 @@ export const TachyonShellMethods = {
|
||||
'/usr/bin/tachyon',
|
||||
{ allowNonZeroWithStdout: true },
|
||||
),
|
||||
getFptnStatus: async () =>
|
||||
callBaseMethod<Tachyon.GetFptnStatus>(
|
||||
Tachyon.AvailableMethods.GET_FPTN_STATUS,
|
||||
[],
|
||||
'/usr/bin/tachyon',
|
||||
{ allowNonZeroWithStdout: true },
|
||||
),
|
||||
getClashApiProxies: async () =>
|
||||
callBaseMethod<ClashAPI.Proxies>(Tachyon.AvailableMethods.CLASH_API, [
|
||||
Tachyon.AvailableClashAPIMethods.GET_PROXIES,
|
||||
|
||||
@@ -294,22 +294,31 @@ function renderDefaultState({
|
||||
'openvpn',
|
||||
].includes(section.action || '');
|
||||
const isServiceNode =
|
||||
['zapret', 'zapret2', 'byedpi'].includes(section.action || '') ||
|
||||
Boolean(section.serviceStatus);
|
||||
['zapret', 'zapret2', 'byedpi', 'wdtt', 'olcrtc', 'fptn'].includes(
|
||||
section.action || '',
|
||||
) || Boolean(section.serviceStatus);
|
||||
|
||||
if (isServiceNode) {
|
||||
const ss = section.serviceStatus;
|
||||
const serviceType =
|
||||
ss?.serviceType ||
|
||||
(['zapret', 'zapret2', 'byedpi'].includes(section.action || '')
|
||||
? (section.action as 'zapret' | 'zapret2' | 'byedpi')
|
||||
(['zapret', 'zapret2', 'byedpi', 'wdtt', 'olcrtc', 'fptn'].includes(
|
||||
section.action || '',
|
||||
)
|
||||
? (section.action as Tachyon.ServiceStatus['serviceType'])
|
||||
: 'zapret');
|
||||
const typeLabel =
|
||||
serviceType === 'zapret'
|
||||
? 'Zapret'
|
||||
: serviceType === 'zapret2'
|
||||
? 'Zapret2'
|
||||
: 'ByeDPI';
|
||||
: serviceType === 'byedpi'
|
||||
? 'ByeDPI'
|
||||
: serviceType === 'wdtt'
|
||||
? 'WDTT'
|
||||
: serviceType === 'olcrtc'
|
||||
? 'OlcRTC'
|
||||
: 'FPTN';
|
||||
const statusColor = ss
|
||||
? ss.ready
|
||||
? 'var(--success-color-medium, green)'
|
||||
|
||||
@@ -71,6 +71,7 @@ export namespace Tachyon {
|
||||
GET_BYEDPI_STATUS = 'get_byedpi_status',
|
||||
GET_WDTT_STATUS = 'get_wdtt_status',
|
||||
GET_OLCRTC_STATUS = 'get_olcrtc_status',
|
||||
GET_FPTN_STATUS = 'get_fptn_status',
|
||||
CLASH_API = 'clash_api',
|
||||
ENABLE = 'enable',
|
||||
DISABLE = 'disable',
|
||||
@@ -204,7 +205,7 @@ export namespace Tachyon {
|
||||
}
|
||||
|
||||
export interface ServiceStatus {
|
||||
serviceType: 'zapret' | 'zapret2' | 'byedpi' | 'wdtt' | 'olcrtc';
|
||||
serviceType: 'zapret' | 'zapret2' | 'byedpi' | 'wdtt' | 'olcrtc' | 'fptn';
|
||||
configured: boolean;
|
||||
ready: boolean;
|
||||
conflict: boolean;
|
||||
@@ -281,6 +282,7 @@ export namespace Tachyon {
|
||||
| 'byedpi'
|
||||
| 'wdtt'
|
||||
| 'olcrtc'
|
||||
| 'fptn'
|
||||
| 'awg'
|
||||
| 'warp'
|
||||
| 'anytls'
|
||||
@@ -362,6 +364,11 @@ export namespace Tachyon {
|
||||
olcrtc_dns_server?: string;
|
||||
olcrtc_subscription_links?: string[];
|
||||
|
||||
access_token?: string;
|
||||
sni?: string;
|
||||
bypass_method?: string;
|
||||
preferred_server?: string;
|
||||
|
||||
selector_proxy_links?: string[];
|
||||
subscription_urls?: string[];
|
||||
interfaces?: string[];
|
||||
@@ -983,6 +990,21 @@ export namespace Tachyon {
|
||||
status_message: string;
|
||||
}
|
||||
|
||||
export interface GetFptnStatus {
|
||||
installed: boolean;
|
||||
configured: boolean;
|
||||
enabled_rule_count: number;
|
||||
service_running: boolean;
|
||||
pid?: number | null;
|
||||
version?: string;
|
||||
binary?: string;
|
||||
tun_interface?: string;
|
||||
route_table?: string;
|
||||
log_file?: string;
|
||||
ready: boolean;
|
||||
status_message?: string;
|
||||
}
|
||||
|
||||
export interface ByedpiCheckResult {
|
||||
byedpi_installed: 0 | 1;
|
||||
byedpi_package_installed: 0 | 1;
|
||||
|
||||
@@ -2056,11 +2056,15 @@ function renderDefaultState({
|
||||
"masque",
|
||||
"openvpn"
|
||||
].includes(section.action || "");
|
||||
const isServiceNode = ["zapret", "zapret2", "byedpi"].includes(section.action || "") || Boolean(section.serviceStatus);
|
||||
const isServiceNode = ["zapret", "zapret2", "byedpi", "wdtt", "olcrtc", "fptn"].includes(
|
||||
section.action || ""
|
||||
) || Boolean(section.serviceStatus);
|
||||
if (isServiceNode) {
|
||||
const ss = section.serviceStatus;
|
||||
const serviceType = ss?.serviceType || (["zapret", "zapret2", "byedpi"].includes(section.action || "") ? section.action : "zapret");
|
||||
const typeLabel = serviceType === "zapret" ? "Zapret" : serviceType === "zapret2" ? "Zapret2" : "ByeDPI";
|
||||
const serviceType = ss?.serviceType || (["zapret", "zapret2", "byedpi", "wdtt", "olcrtc", "fptn"].includes(
|
||||
section.action || ""
|
||||
) ? section.action : "zapret");
|
||||
const typeLabel = serviceType === "zapret" ? "Zapret" : serviceType === "zapret2" ? "Zapret2" : serviceType === "byedpi" ? "ByeDPI" : serviceType === "wdtt" ? "WDTT" : serviceType === "olcrtc" ? "OlcRTC" : "FPTN";
|
||||
const statusColor = ss ? ss.ready ? "var(--success-color-medium, green)" : ss.conflict ? "var(--error-color-medium, red)" : ss.configured ? "var(--warn-color-medium, orange)" : "var(--primary-color-low, lightgray)" : "var(--primary-color-low, lightgray)";
|
||||
const statusText = ss ? ss.ready ? _("Running") : ss.conflict ? _("Conflict") : ss.configured ? _("Stopped") : _("Not configured") : _("Unknown");
|
||||
return E("div", { class: "tachyon_dashboard-page__outbound-section" }, [
|
||||
@@ -3049,6 +3053,7 @@ var Tachyon;
|
||||
AvailableMethods2["GET_BYEDPI_STATUS"] = "get_byedpi_status";
|
||||
AvailableMethods2["GET_WDTT_STATUS"] = "get_wdtt_status";
|
||||
AvailableMethods2["GET_OLCRTC_STATUS"] = "get_olcrtc_status";
|
||||
AvailableMethods2["GET_FPTN_STATUS"] = "get_fptn_status";
|
||||
AvailableMethods2["CLASH_API"] = "clash_api";
|
||||
AvailableMethods2["ENABLE"] = "enable";
|
||||
AvailableMethods2["DISABLE"] = "disable";
|
||||
@@ -3388,6 +3393,12 @@ var TachyonShellMethods = {
|
||||
"/usr/bin/tachyon",
|
||||
{ allowNonZeroWithStdout: true }
|
||||
),
|
||||
getFptnStatus: async () => callBaseMethod(
|
||||
Tachyon.AvailableMethods.GET_FPTN_STATUS,
|
||||
[],
|
||||
"/usr/bin/tachyon",
|
||||
{ allowNonZeroWithStdout: true }
|
||||
),
|
||||
getClashApiProxies: async () => callBaseMethod(Tachyon.AvailableMethods.CLASH_API, [
|
||||
Tachyon.AvailableClashAPIMethods.GET_PROXIES
|
||||
]),
|
||||
@@ -4691,7 +4702,8 @@ var ACTION_DISPLAY_NAMES = {
|
||||
mieru: "Mieru",
|
||||
sudoku: "Sudoku",
|
||||
masque: "MASQUE",
|
||||
openvpn: "OpenVPN"
|
||||
openvpn: "OpenVPN",
|
||||
fptn: "FPTN"
|
||||
};
|
||||
function isConnectionAction(action) {
|
||||
return Boolean(
|
||||
@@ -4700,7 +4712,9 @@ function isConnectionAction(action) {
|
||||
}
|
||||
function isServiceAction(action) {
|
||||
return Boolean(
|
||||
action && ["zapret", "zapret2", "byedpi", "wdtt", "olcrtc"].includes(action)
|
||||
action && ["zapret", "zapret2", "byedpi", "wdtt", "olcrtc", "fptn"].includes(
|
||||
action
|
||||
)
|
||||
);
|
||||
}
|
||||
function hasSubscriptionSources(section) {
|
||||
@@ -5580,6 +5594,22 @@ async function getDashboardSections(options = {}) {
|
||||
statusMessage: s.status_message
|
||||
};
|
||||
}
|
||||
} else if (serviceType === "fptn") {
|
||||
const result = await TachyonShellMethods.getFptnStatus();
|
||||
if (result.success && result.data) {
|
||||
const s = result.data;
|
||||
return {
|
||||
serviceType: "fptn",
|
||||
configured: Boolean(s.configured),
|
||||
ready: Boolean(s.ready),
|
||||
conflict: false,
|
||||
runningProcesses: s.service_running ? 1 : 0,
|
||||
expectedProcesses: s.configured ? 1 : 0,
|
||||
restartCount: 0,
|
||||
unstable: false,
|
||||
statusMessage: s.status_message || (s.ready ? _("Running") : _("Stopped"))
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (_error) {
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ const ROUTING_ACTIONS = [
|
||||
"byedpi",
|
||||
"wdtt",
|
||||
"olcrtc",
|
||||
"fptn",
|
||||
"awg",
|
||||
"warp",
|
||||
"anytls",
|
||||
@@ -491,6 +492,7 @@ const actionProvidersAvailabilityState = {
|
||||
byedpiInstalled: false,
|
||||
wdttInstalled: false,
|
||||
olcrtcInstalled: false,
|
||||
fptnInstalled: false,
|
||||
torInstalled: false,
|
||||
singBoxExtended: false,
|
||||
};
|
||||
@@ -685,6 +687,12 @@ function updateActionProvidersAvailabilityState(nextState) {
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof nextState.fptnInstalled !== "undefined") {
|
||||
actionProvidersAvailabilityState.fptnInstalled = Boolean(
|
||||
nextState.fptnInstalled,
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof nextState.singBoxExtended !== "undefined") {
|
||||
actionProvidersAvailabilityState.singBoxExtended = Boolean(
|
||||
nextState.singBoxExtended,
|
||||
@@ -711,6 +719,7 @@ function updateActionProvidersAvailabilityFromSystemInfo(systemInfo) {
|
||||
byedpiInstalled: Boolean(systemInfo.byedpi_installed),
|
||||
wdttInstalled: Boolean(systemInfo.wdtt_installed),
|
||||
olcrtcInstalled: Boolean(systemInfo.olcrtc_installed),
|
||||
fptnInstalled: Boolean(systemInfo.fptn_installed),
|
||||
singBoxExtended: Boolean(systemInfo.sing_box_extended),
|
||||
torInstalled: Boolean(systemInfo.tor_installed),
|
||||
});
|
||||
@@ -2181,6 +2190,10 @@ function isDownloadThroughTargetSection(section, currentSectionId) {
|
||||
return isOlcrtcInstalledForUi();
|
||||
}
|
||||
|
||||
if (action === "fptn") {
|
||||
return isFptnInstalledForUi();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4625,6 +4638,10 @@ function isOlcrtcInstalledForUi() {
|
||||
return actionProvidersAvailabilityState.olcrtcInstalled;
|
||||
}
|
||||
|
||||
function isFptnInstalledForUi() {
|
||||
return actionProvidersAvailabilityState.fptnInstalled;
|
||||
}
|
||||
|
||||
function isSingBoxExtendedForUi() {
|
||||
return actionProvidersAvailabilityState.singBoxExtended;
|
||||
}
|
||||
@@ -4660,6 +4677,8 @@ function getActionOptionLabel(action) {
|
||||
return "WDTT";
|
||||
case "olcrtc":
|
||||
return "OlcRTC";
|
||||
case "fptn":
|
||||
return "FPTN";
|
||||
|
||||
case "awg":
|
||||
return "AmneziaWG";
|
||||
@@ -4710,6 +4729,10 @@ function getRuleActionDisplayValue(section_id) {
|
||||
return "OlcRTC";
|
||||
}
|
||||
|
||||
if (action === "fptn") {
|
||||
return "FPTN";
|
||||
}
|
||||
|
||||
if (action === "awg") {
|
||||
return "AmneziaWG";
|
||||
}
|
||||
@@ -4782,6 +4805,9 @@ function populateActionOptionValues(option) {
|
||||
if (isOlcrtcInstalledForUi()) {
|
||||
option.value("olcrtc", getActionOptionLabel("olcrtc"));
|
||||
}
|
||||
if (isFptnInstalledForUi()) {
|
||||
option.value("fptn", getActionOptionLabel("fptn"));
|
||||
}
|
||||
option.value("hosts", getActionOptionLabel("hosts"));
|
||||
}
|
||||
|
||||
@@ -7763,6 +7789,10 @@ function createSectionContent(section) {
|
||||
o.load = function (section_id) {
|
||||
return ensureActionProvidersAvailabilityLoaded().then(() => {
|
||||
populateActionOptionValues(this);
|
||||
const configured = getRuleConfiguredAction(section_id);
|
||||
if (configured && !this.keylist.includes(configured)) {
|
||||
this.value(configured, getActionOptionLabel(configured));
|
||||
}
|
||||
return this.cfgvalue(section_id);
|
||||
});
|
||||
};
|
||||
@@ -8168,6 +8198,52 @@ function createSectionContent(section) {
|
||||
o.depends("action", "olcrtc");
|
||||
o.modalonly = true;
|
||||
|
||||
// ─── FPTN Fields ───────────────────────────────────────────────────────
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.Value,
|
||||
"access_token",
|
||||
_("FPTN Access Token"),
|
||||
);
|
||||
o.depends("action", "fptn");
|
||||
o.password = true;
|
||||
o.rmempty = false;
|
||||
o.modalonly = true;
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.Value,
|
||||
"sni",
|
||||
_("FPTN SNI"),
|
||||
_("Optional: override TLS SNI for FPTN connection"),
|
||||
);
|
||||
o.depends("action", "fptn");
|
||||
o.optional = true;
|
||||
o.modalonly = true;
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.Value,
|
||||
"bypass_method",
|
||||
_("FPTN Bypass Method"),
|
||||
_("Optional: override bypass method (e.g. quic, tcp)"),
|
||||
);
|
||||
o.depends("action", "fptn");
|
||||
o.optional = true;
|
||||
o.modalonly = true;
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.Value,
|
||||
"preferred_server",
|
||||
_("FPTN Preferred Server"),
|
||||
_("Optional: preferred FPTN server address"),
|
||||
);
|
||||
o.depends("action", "fptn");
|
||||
o.optional = true;
|
||||
o.modalonly = true;
|
||||
|
||||
// ─── Hosts Import Helpers ──────────────────────────────────────────────
|
||||
|
||||
function parseHostsFile(text, options) {
|
||||
@@ -11310,6 +11386,7 @@ const ACTION_COLORS = {
|
||||
byedpi: "#d35400",
|
||||
wdtt: "#27ae60",
|
||||
olcrtc: "#2980b9",
|
||||
fptn: "#e74c3c",
|
||||
awg: "#008080",
|
||||
warp: "#e67e22",
|
||||
anytls: "#16a085",
|
||||
|
||||
@@ -114,6 +114,7 @@ function show_help() {
|
||||
print(" get_byedpi_status Get ByeDPI provider and Tachyon-managed ciadpi status\n");
|
||||
print(" get_wdtt_status Get WDTT provider and Tachyon-managed wdtt status\n");
|
||||
print(" get_olcrtc_status Get OlcRTC provider and Tachyon-managed olcrtc status\n");
|
||||
print(" get_fptn_status Get FPTN provider and Tachyon-managed fptn status\n");
|
||||
print(" get_system_info Get system information in JSON format\n");
|
||||
print(" get_server_capabilities Get server UI capabilities in JSON format\n");
|
||||
print(" get_ui_capabilities Get lightweight UI capabilities in JSON format\n");
|
||||
@@ -230,6 +231,7 @@ function command_spec(command) {
|
||||
get_byedpi_status: [ "diagnostics/runtime.uc", "get-byedpi-status", 0 ],
|
||||
get_wdtt_status: [ "diagnostics/runtime.uc", "get-wdtt-status", 0 ],
|
||||
get_olcrtc_status: [ "diagnostics/runtime.uc", "get-olcrtc-status", 0 ],
|
||||
get_fptn_status: [ "diagnostics/runtime.uc", "get-fptn-status", 0 ],
|
||||
get_tailscale_status: [ "diagnostics/runtime.uc", "get-tailscale-status", 0 ],
|
||||
get_tailscale_peers: [ "diagnostics/runtime.uc", "get-tailscale-peers", 0 ],
|
||||
tailscale_restart: [ "providers/tailscale/runtime.uc", "start-runtime", 0 ],
|
||||
|
||||
@@ -5320,6 +5320,8 @@ else if (mode == "get-wdtt-status")
|
||||
exit(module_passthrough(WDTT_RUNTIME_UC, [ "status" ]));
|
||||
else if (mode == "get-olcrtc-status")
|
||||
exit(module_passthrough(OLCRTC_RUNTIME_UC, [ "status" ]));
|
||||
else if (mode == "get-fptn-status")
|
||||
exit(module_passthrough(FPTN_RUNTIME_UC, [ "status" ]));
|
||||
else if (mode == "get-tailscale-status")
|
||||
exit(module_passthrough(TAILSCALE_RUNTIME_UC, [ "status" ]));
|
||||
else if (mode == "get-tailscale-peers")
|
||||
|
||||
@@ -7,6 +7,7 @@ UPDATER_UC="$ROOT_DIR/tachyon/files/usr/lib/components/updater.uc"
|
||||
PACKAGES_UC="$ROOT_DIR/tachyon/files/usr/lib/core/packages.uc"
|
||||
FPTN_RUNTIME_UC="$ROOT_DIR/tachyon/files/usr/lib/providers/fptn/runtime.uc"
|
||||
STATE_UC="$ROOT_DIR/tachyon/files/usr/lib/service/state.uc"
|
||||
DIAGNOSTICS_UC="$ROOT_DIR/tachyon/files/usr/lib/diagnostics/runtime.uc"
|
||||
|
||||
WORK_DIR="$(mktemp -d)"
|
||||
cleanup() {
|
||||
@@ -115,4 +116,8 @@ EOF_FIXTURE2
|
||||
SIG_2="$(ucode_run "$STATE_UC" fptn-runtime-signature-fixture "$WORK_DIR/state_fixture2.json")"
|
||||
[ "$SIG_1" != "$SIG_2" ] || fail "fptn signature should differ when token changes"
|
||||
|
||||
# 5. Test diagnostics runtime dispatch for get-fptn-status
|
||||
STATUS_OUT="$(TACHYON_LIB_DIR="$TACHYON_LIB" ucode_run "$DIAGNOSTICS_UC" get-fptn-status)"
|
||||
echo "$STATUS_OUT" | grep -q '"ready":' || fail "get-fptn-status should return status json"
|
||||
|
||||
echo "fptn component tests passed"
|
||||
|
||||
Reference in New Issue
Block a user