feat(services): сделать multi-FQDN привязки first-class в UI
Исправить prune при domains: [], показать все FQDN в каталоге/kanban, улучшить sheet привязок и панель на домене; убрать мёртвый код. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -1172,97 +1172,95 @@ export async function updateConfig(
|
||||
let removedBindingIds: number[] = [];
|
||||
|
||||
if (req.domains) {
|
||||
if (req.domains.length > 0) {
|
||||
for (const input of req.domains) {
|
||||
const fqdn = input.fqdn.trim();
|
||||
if (!fqdn) continue;
|
||||
const targetCname = bindingTargetCname(input);
|
||||
const targetIps = bindingTargetIps(input);
|
||||
if (!targetCname) {
|
||||
validateTargetIpsInPool(targetIps, ips);
|
||||
} else if (targetIps.length > 0) {
|
||||
throw AppError.validation(
|
||||
`укажите либо IP, либо CNAME для ${fqdn}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { zoneName, hostname } = parseFqdn(fqdn, knownZones);
|
||||
const domainId = await resolveDomainId(db, cf, zoneName);
|
||||
|
||||
const binding =
|
||||
repos.findBinding(db, id, domainId, hostname) ??
|
||||
repos.insertBinding(db, domainId, id, hostname, null);
|
||||
|
||||
keptBindingIds.push(binding.id);
|
||||
|
||||
const targetIpWeights = input.target_ip_weights ?? {};
|
||||
const targetIpPriorities = input.target_ip_priorities ?? {};
|
||||
const bindingIpEntries = (targetCname ? [] : targetIps).map((ip) => ({
|
||||
ip,
|
||||
weight: targetIpWeights[ip] ?? 1,
|
||||
priority: targetIpPriorities[ip] ?? 1,
|
||||
}));
|
||||
repos.replaceBindingIpsWithMeta(db, binding.id, bindingIpEntries);
|
||||
repos.setBindingCnameTarget(db, binding.id, targetCname);
|
||||
|
||||
if (
|
||||
input.lb_mode !== undefined ||
|
||||
input.health_check_enabled !== undefined ||
|
||||
input.health_check_type !== undefined ||
|
||||
input.health_check_port !== undefined ||
|
||||
input.health_check_path !== undefined ||
|
||||
input.health_check_expected_status !== undefined ||
|
||||
input.health_check_interval_sec !== undefined ||
|
||||
input.health_check_timeout_ms !== undefined ||
|
||||
input.health_check_verify_tls !== undefined
|
||||
) {
|
||||
repos.updateBindingLbConfig(db, binding.id, {
|
||||
lb_mode: input.lb_mode,
|
||||
health_check_enabled: input.health_check_enabled,
|
||||
health_check_type: input.health_check_type,
|
||||
health_check_port: input.health_check_port,
|
||||
health_check_path: input.health_check_path,
|
||||
health_check_expected_status: input.health_check_expected_status,
|
||||
health_check_interval_sec: input.health_check_interval_sec,
|
||||
health_check_timeout_ms: input.health_check_timeout_ms,
|
||||
health_check_verify_tls: input.health_check_verify_tls,
|
||||
});
|
||||
}
|
||||
|
||||
if (pushDns) {
|
||||
let effectiveIps = targetIps;
|
||||
const refreshedBinding = repos.getBinding(db, binding.id);
|
||||
if (refreshedBinding.health_check_enabled) {
|
||||
const activeIps = computeActiveIps(db, "binding", binding.id);
|
||||
if (activeIps.length > 0) {
|
||||
effectiveIps = activeIps;
|
||||
}
|
||||
}
|
||||
await syncBindingDns(
|
||||
db,
|
||||
cf,
|
||||
binding.id,
|
||||
domainId,
|
||||
hostname,
|
||||
effectiveIps,
|
||||
targetCname,
|
||||
);
|
||||
}
|
||||
for (const input of req.domains) {
|
||||
const fqdn = input.fqdn.trim();
|
||||
if (!fqdn) continue;
|
||||
const targetCname = bindingTargetCname(input);
|
||||
const targetIps = bindingTargetIps(input);
|
||||
if (!targetCname) {
|
||||
validateTargetIpsInPool(targetIps, ips);
|
||||
} else if (targetIps.length > 0) {
|
||||
throw AppError.validation(
|
||||
`укажите либо IP, либо CNAME для ${fqdn}`,
|
||||
);
|
||||
}
|
||||
|
||||
const removed = repos.bindingsToRemove(db, id, keptBindingIds);
|
||||
removedBindingIds = removed.map((binding) => binding.id);
|
||||
for (const binding of removed) {
|
||||
await cleanupBindingDns(
|
||||
const { zoneName, hostname } = parseFqdn(fqdn, knownZones);
|
||||
const domainId = await resolveDomainId(db, cf, zoneName);
|
||||
|
||||
const binding =
|
||||
repos.findBinding(db, id, domainId, hostname) ??
|
||||
repos.insertBinding(db, domainId, id, hostname, null);
|
||||
|
||||
keptBindingIds.push(binding.id);
|
||||
|
||||
const targetIpWeights = input.target_ip_weights ?? {};
|
||||
const targetIpPriorities = input.target_ip_priorities ?? {};
|
||||
const bindingIpEntries = (targetCname ? [] : targetIps).map((ip) => ({
|
||||
ip,
|
||||
weight: targetIpWeights[ip] ?? 1,
|
||||
priority: targetIpPriorities[ip] ?? 1,
|
||||
}));
|
||||
repos.replaceBindingIpsWithMeta(db, binding.id, bindingIpEntries);
|
||||
repos.setBindingCnameTarget(db, binding.id, targetCname);
|
||||
|
||||
if (
|
||||
input.lb_mode !== undefined ||
|
||||
input.health_check_enabled !== undefined ||
|
||||
input.health_check_type !== undefined ||
|
||||
input.health_check_port !== undefined ||
|
||||
input.health_check_path !== undefined ||
|
||||
input.health_check_expected_status !== undefined ||
|
||||
input.health_check_interval_sec !== undefined ||
|
||||
input.health_check_timeout_ms !== undefined ||
|
||||
input.health_check_verify_tls !== undefined
|
||||
) {
|
||||
repos.updateBindingLbConfig(db, binding.id, {
|
||||
lb_mode: input.lb_mode,
|
||||
health_check_enabled: input.health_check_enabled,
|
||||
health_check_type: input.health_check_type,
|
||||
health_check_port: input.health_check_port,
|
||||
health_check_path: input.health_check_path,
|
||||
health_check_expected_status: input.health_check_expected_status,
|
||||
health_check_interval_sec: input.health_check_interval_sec,
|
||||
health_check_timeout_ms: input.health_check_timeout_ms,
|
||||
health_check_verify_tls: input.health_check_verify_tls,
|
||||
});
|
||||
}
|
||||
|
||||
if (pushDns) {
|
||||
let effectiveIps = targetIps;
|
||||
const refreshedBinding = repos.getBinding(db, binding.id);
|
||||
if (refreshedBinding.health_check_enabled) {
|
||||
const activeIps = computeActiveIps(db, "binding", binding.id);
|
||||
if (activeIps.length > 0) {
|
||||
effectiveIps = activeIps;
|
||||
}
|
||||
}
|
||||
await syncBindingDns(
|
||||
db,
|
||||
cf,
|
||||
binding.id,
|
||||
binding.domain_id,
|
||||
binding.hostname,
|
||||
domainId,
|
||||
hostname,
|
||||
effectiveIps,
|
||||
targetCname,
|
||||
);
|
||||
}
|
||||
repos.deleteBindingsExcept(db, id, keptBindingIds);
|
||||
}
|
||||
|
||||
const removed = repos.bindingsToRemove(db, id, keptBindingIds);
|
||||
removedBindingIds = removed.map((binding) => binding.id);
|
||||
for (const binding of removed) {
|
||||
await cleanupBindingDns(
|
||||
db,
|
||||
cf,
|
||||
binding.id,
|
||||
binding.domain_id,
|
||||
binding.hostname,
|
||||
);
|
||||
}
|
||||
repos.deleteBindingsExcept(db, id, keptBindingIds);
|
||||
} else if (ipsUpdated) {
|
||||
const bindings = repos.listBindingsByService(db, id);
|
||||
for (const binding of bindings) {
|
||||
@@ -1278,8 +1276,11 @@ export async function updateConfig(
|
||||
}
|
||||
|
||||
service = repos.getService(db, id);
|
||||
const remainingBindings = repos.listBindingsByService(db, id);
|
||||
if (shouldPushDns(db, service)) {
|
||||
await syncServiceBindingsToDns(db, cf, id);
|
||||
if (remainingBindings.length > 0) {
|
||||
await syncServiceBindingsToDns(db, cf, id);
|
||||
}
|
||||
await syncGroupDomainForService(db, cf, id);
|
||||
} else if (
|
||||
req.domains &&
|
||||
|
||||
Reference in New Issue
Block a user