@mesh-tech/mesh-cli
Version:
CLI for Mesh platform development utilities
61 lines (60 loc) • 2.05 kB
JavaScript
import { execFileSync } from "node:child_process";
import * as fs from "node:fs";
import * as path from "node:path";
import { reserveSsmLocalPortCandidate, preferredSsmLocalPort } from "../commands/dev.js";
import { CONFIG_DIR, atomicWriteFileSync } from "../commands/login.js";
export const PORT_BLOCK = 3000;
export function tenantPortIndex(tenant, registryPath) {
const p = registryPath ?? path.join(CONFIG_DIR, "tailscale", "port-registry.json");
let reg;
try {
reg = JSON.parse(fs.readFileSync(p, "utf8"));
}
catch {
reg = { mesh: 0 };
}
if (tenant in reg)
return reg[tenant];
const idx = Math.max(-1, ...Object.values(reg)) + 1;
reg[tenant] = idx;
fs.mkdirSync(path.dirname(p), { recursive: true });
atomicWriteFileSync(p, JSON.stringify(reg, null, 2), 0o600);
return idx;
}
export const TUNNEL_NAME_BY_BASTION_KEY = {
"temporal-frontend": "temporal",
"temporal-ui": "temporal-ui",
rds: "rds",
};
export function resolveTunnelTargets(services, resolveIp, portOffset = 0) {
const reserved = new Set();
const targets = [];
for (const [key, svc] of Object.entries(services)) {
const name = TUNNEL_NAME_BY_BASTION_KEY[key];
if (!name)
continue;
const targetIp = resolveIp(svc.host);
if (!targetIp)
continue;
const localPort = reserveSsmLocalPortCandidate(svc.port, reserved, preferredSsmLocalPort(svc.port) + portOffset);
targets.push({ name, localPort, targetHost: svc.host, targetIp, remotePort: svc.port });
}
return targets;
}
export function resolveElbIp(host) {
try {
const out = execFileSync("dig", ["+short", host, "@1.1.1.1"], {
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
});
const ip = out
.trim()
.split("\n")
.map((l) => l.trim())
.find((l) => /^\d+\.\d+\.\d+\.\d+$/.test(l));
return ip ?? null;
}
catch {
return null;
}
}