add posibility to choose witch tools should used
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
+10
-1
@@ -10,9 +10,18 @@ targets:
|
|||||||
hosts:
|
hosts:
|
||||||
- url: http://127.0.0.1:7088
|
- url: http://127.0.0.1:7088
|
||||||
name: proxy-city
|
name: proxy-city
|
||||||
|
metadata:
|
||||||
|
location: Moscow
|
||||||
|
provider: CityNet
|
||||||
|
country: RU
|
||||||
|
tags: [primary, city]
|
||||||
- url: http://127.0.0.1:7089
|
- url: http://127.0.0.1:7089
|
||||||
name: proxy-optima
|
name: proxy-optima
|
||||||
|
metadata:
|
||||||
|
location: Saint-Petersburg
|
||||||
|
provider: Optima
|
||||||
|
country: RU
|
||||||
|
tags: [secondary]
|
||||||
endpoints:
|
endpoints:
|
||||||
- /testmontools/curl
|
- /testmontools/curl
|
||||||
- /testmontools/traceroute
|
- /testmontools/traceroute
|
||||||
|
|||||||
@@ -12,12 +12,41 @@ const configPath = path.join(__dirname, "config.yml");
|
|||||||
const config = yaml.load(fs.readFileSync(configPath, "utf8"));
|
const config = yaml.load(fs.readFileSync(configPath, "utf8"));
|
||||||
|
|
||||||
const PORT = config.server?.port || 4000;
|
const PORT = config.server?.port || 4000;
|
||||||
const HOSTS = config.targets?.hosts || [{url: "http://127.0.0.1:7088", name: "my-server"}];
|
const HOSTS = config.targets?.hosts || [{ url: "http://127.0.0.1:7088", name: "my-server", metadata: {} }];
|
||||||
const ENDPOINTS = config.targets?.endpoints || [];
|
const ENDPOINTS = config.targets?.endpoints || [];
|
||||||
const TIMEOUT = config.targets?.timeout || 120_000;
|
const TIMEOUT = config.targets?.timeout || 120_000;
|
||||||
|
|
||||||
|
// ─── Check name → endpoint suffix mapping ────────────────────────────────────
|
||||||
|
// Allows the client to pass ["ping", "curl", "tracert"] in any casing
|
||||||
|
const CHECK_MAP = {
|
||||||
|
ping: "/testmontools/ping",
|
||||||
|
curl: "/testmontools/curl",
|
||||||
|
tracert: "/testmontools/traceroute",
|
||||||
|
traceroute: "/testmontools/traceroute",
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the list of endpoints to run.
|
||||||
|
* @param {string[]} checks - e.g. ["ping", "curl"] or [] (= all)
|
||||||
|
* @returns {string[]} deduplicated endpoint paths present in ENDPOINTS
|
||||||
|
*/
|
||||||
|
function resolveEndpoints(checks) {
|
||||||
|
if (!Array.isArray(checks) || checks.length === 0) {
|
||||||
|
return ENDPOINTS; // run everything declared in config
|
||||||
|
}
|
||||||
|
|
||||||
|
const requested = new Set(
|
||||||
|
checks
|
||||||
|
.map((c) => CHECK_MAP[c.toLowerCase().trim()])
|
||||||
|
.filter(Boolean)
|
||||||
|
);
|
||||||
|
|
||||||
|
// keep only endpoints that are both requested AND declared in config
|
||||||
|
return ENDPOINTS.filter((ep) => requested.has(ep));
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`[config] loaded from ${configPath}`);
|
console.log(`[config] loaded from ${configPath}`);
|
||||||
console.log(`[config] hosts (${HOSTS.length}):`, HOSTS);
|
console.log(`[config] hosts (${HOSTS.length}):`, HOSTS.map(h => `${h.name} (${h.url})`));
|
||||||
console.log(`[config] endpoints:`, ENDPOINTS);
|
console.log(`[config] endpoints:`, ENDPOINTS);
|
||||||
|
|
||||||
// ─── Express + Socket.io ──────────────────────────────────────────────────────
|
// ─── Express + Socket.io ──────────────────────────────────────────────────────
|
||||||
@@ -32,7 +61,7 @@ app.use(express.json());
|
|||||||
|
|
||||||
// ─── POST /api/parallel-fetch ─────────────────────────────────────────────────
|
// ─── POST /api/parallel-fetch ─────────────────────────────────────────────────
|
||||||
app.post("/api/parallel-fetch", async (req, res) => {
|
app.post("/api/parallel-fetch", async (req, res) => {
|
||||||
const { socketId, url, timeout = TIMEOUT } = req.body;
|
const { socketId, url, timeout = TIMEOUT, checks = [] } = req.body;
|
||||||
|
|
||||||
if (!socketId || !url) {
|
if (!socketId || !url) {
|
||||||
return res.status(400).json({ error: "socketId and url are required" });
|
return res.status(400).json({ error: "socketId and url are required" });
|
||||||
@@ -43,13 +72,22 @@ app.post("/api/parallel-fetch", async (req, res) => {
|
|||||||
return res.status(400).json({ error: `Socket ${socketId} not found` });
|
return res.status(400).json({ error: `Socket ${socketId} not found` });
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json({ status: "started" });
|
const activeEndpoints = resolveEndpoints(checks);
|
||||||
|
|
||||||
|
if (activeEndpoints.length === 0) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "No valid endpoints resolved. Check 'checks' values or config endpoints.",
|
||||||
|
validCheckNames: Object.keys(CHECK_MAP),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({ status: "started", endpoints: activeEndpoints });
|
||||||
|
|
||||||
const tasks = HOSTS.flatMap((host) =>
|
const tasks = HOSTS.flatMap((host) =>
|
||||||
ENDPOINTS.map((endpoint) => ({ host, endpoint }))
|
activeEndpoints.map((endpoint) => ({ host, endpoint }))
|
||||||
);
|
);
|
||||||
|
|
||||||
socket.emit("batch:start", { url, total: tasks.length });
|
socket.emit("batch:start", { url, total: tasks.length, endpoints: activeEndpoints });
|
||||||
|
|
||||||
const promises = tasks.map(({ host, endpoint }) => {
|
const promises = tasks.map(({ host, endpoint }) => {
|
||||||
const fullUrl = host.url + endpoint;
|
const fullUrl = host.url + endpoint;
|
||||||
@@ -64,10 +102,12 @@ app.post("/api/parallel-fetch", async (req, res) => {
|
|||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const elapsed = Date.now() - start;
|
const elapsed = Date.now() - start;
|
||||||
console.log(`[OK] ${host} ${endpoint} (${elapsed}ms)`);
|
console.log(`[OK] ${host.name} ${endpoint} (${elapsed}ms)`);
|
||||||
|
|
||||||
socket.emit("tool:response", {
|
socket.emit("tool:response", {
|
||||||
host: host.url,
|
host: host.url,
|
||||||
serverName: host.name,
|
serverName: host.name,
|
||||||
|
metadata: host.metadata ?? {}, // ← метаданные хоста
|
||||||
endpoint,
|
endpoint,
|
||||||
ok: true,
|
ok: true,
|
||||||
status: response.status,
|
status: response.status,
|
||||||
@@ -77,10 +117,12 @@ app.post("/api/parallel-fetch", async (req, res) => {
|
|||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
const elapsed = Date.now() - start;
|
const elapsed = Date.now() - start;
|
||||||
console.log(`[ERROR] ${host} ${endpoint} (${elapsed}ms) — ${err.message}`);
|
console.log(`[ERROR] ${host.name} ${endpoint} (${elapsed}ms) — ${err.message}`);
|
||||||
|
|
||||||
socket.emit("tool:error", {
|
socket.emit("tool:error", {
|
||||||
host: host.url,
|
host: host.url,
|
||||||
serverName: host.name,
|
serverName: host.name,
|
||||||
|
metadata: host.metadata ?? {}, // ← метаданные хоста
|
||||||
endpoint,
|
endpoint,
|
||||||
ok: false,
|
ok: false,
|
||||||
error: err.message,
|
error: err.message,
|
||||||
@@ -98,7 +140,7 @@ app.post("/api/parallel-fetch", async (req, res) => {
|
|||||||
|
|
||||||
// ─── Health ───────────────────────────────────────────────────────────────────
|
// ─── Health ───────────────────────────────────────────────────────────────────
|
||||||
app.get("/health", (_req, res) =>
|
app.get("/health", (_req, res) =>
|
||||||
res.json({ ok: true, hosts: HOSTS, endpoints: ENDPOINTS })
|
res.json({ ok: true, hosts: HOSTS, endpoints: ENDPOINTS, checkMap: CHECK_MAP })
|
||||||
);
|
);
|
||||||
|
|
||||||
// ─── Socket lifecycle ─────────────────────────────────────────────────────────
|
// ─── Socket lifecycle ─────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user