diff --git a/CHANGELOG.md b/CHANGELOG.md index b0281f6..bb713af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ Release history focused on **features, settings, default behavior, compatibility ## 0.34.8 -- Docker vhosts now use container names by default instead of image/port names. Existing automatic hostnames are updated; manual hostnames and aliases stay unchanged. Docker Agent updated to 1.0.1. +- Docker vhosts now use container names by default instead of image/port names. Existing saved hostnames and manually configured aliases remain unchanged. Docker Agent updated to 1.0.1. ## 0.34.7 diff --git a/src/admin/web/docker.js b/src/admin/web/docker.js index 8194ae3..aff1a42 100644 --- a/src/admin/web/docker.js +++ b/src/admin/web/docker.js @@ -96,19 +96,6 @@ box.append(inputNode); field.append(box); field.title = t("dockerAliasesHelp"); inputNode.title = t("dockerAliasesHelp"); for (const value of initial) { try { add(value, false); } catch { } } return { node: field, read() { if (inputNode.value.trim()) consume(inputNode.value); return [...values]; }, count: () => values.length, input: inputNode }; } - function legacyHostname(assignment) { return assignment?.hostname || assignment?.subdomain || ""; } - function legacyDockerName(service) { - const key = service?.key || ""; - const compose = /^compose:([^/]+)\/([^/]+)\/([^:]+):(\d+)\/tcp$/.exec(key); - const container = /^container:(.*):(\d+)\/tcp$/.exec(key); - if (!compose && !container) return null; - const base = compose ? `${compose[1]}-${compose[2]}${compose[3] === "1" ? "" : `-${compose[3]}`}-${compose[4]}` : `${container[1]}-${container[2]}`; - return base.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 48).replace(/-$/, ""); - } - function displayHostname(assignment, service) { - const host = legacyHostname(assignment); - return service && host === legacyDockerName(service) ? service.technical_name : (host || service?.technical_name || ""); - } function serviceBindings(service) { if (!service) return []; if (Array.isArray(service.bindings) && service.bindings.length) return service.bindings; @@ -396,7 +383,7 @@ const key = assignment?.service_key || service.key, row = el("article", undefined, "docker-service-row"); row.dataset.key = key; row.dataset.viewKey = viewKey(agent.id, key); const runtime = runtimeFor(agent.id, key), member = runtime?.members?.[0], technicalName = service?.technical_name || assignment?.service_key || ""; row.dockerSort = { - service: technicalName.toLowerCase(), hostname: String(displayHostname(assignment, service) || technicalName).toLowerCase(), + service: technicalName.toLowerCase(), hostname: String(assignment?.hostname || service?.technical_name || "" || technicalName).toLowerCase(), status: stale ? 4 : assignment?.enabled === false || !assignment ? 3 : member?.status === "up" ? 0 : member?.status === "down" ? 1 : 2, backend: String(assignment?.target_ip || agent.default_target_ip || inventory?.public_ip || "").toLowerCase(), scheme: String(assignment?.scheme || "http"), published: assignment && assignment.enabled !== false ? 0 : 1, }; @@ -423,12 +410,12 @@ liveLogs.disabled = !publish.checked || !poolRoutes.some(item => item.agent_id === agent.id && item.service_key === key && item.pool_id); publish.setAttribute("aria-checked", String(publish.checked)); }; - syncOpenActions(displayHostname(assignment, service)); + syncOpenActions(assignment?.hostname || service?.technical_name || ""); const quickActions = el("div", undefined, "docker-service-quick-actions"); quickActions.append(openApp, liveLogs); const headActions = el("div", undefined, "docker-service-head-actions"); headActions.append(runtimeSummary(runtime, assignment, stale), quickActions, visibility); top.append(publishLabel, meta, headActions); row.append(top); const editor = el("details", undefined, "docker-service-editor"), editorSummary = el("summary"), editorTitle = el("span", t("dockerConfigureService")), editorHint = el("small", "", "fine docker-config-hint"); editorSummary.append(editorTitle, editorHint); editor.append(editorSummary); - const route = el("div", undefined, "docker-route-grid"), host = input(displayHostname(assignment, service), "text", "docker-hostname"); host.maxLength = 253; host.placeholder = service?.technical_name || "app1"; + const route = el("div", undefined, "docker-route-grid"), host = input(assignment?.hostname || service?.technical_name || "", "text", "docker-hostname"); host.maxLength = 253; host.placeholder = service?.technical_name || "app1"; row.dockerSyncActions = () => syncOpenActions(host.value); let aliases; const aliasChanged = () => { updateHint?.(); row.dispatchEvent(new Event("input", { bubbles: true })); }; aliases = aliasEditor(assignment?.aliases || [], aliasChanged); row._readAliases = aliases.read; const target = el("select", undefined, "docker-target-ip"), auto = el("option", agent.default_target_ip ? `${t("dockerBackendIpAuto")} (${agent.default_target_ip})` : t("dockerBackendIpAuto")); auto.value = ""; target.append(auto); for (const [ip, label] of targetOptions(inventory, service, assignment, agent)) { const option = el("option", label); option.value = ip; target.append(option); } target.value = assignment?.target_ip || ""; diff --git a/src/docker/reconcile.rs b/src/docker/reconcile.rs index 8b539ae..42bb26f 100644 --- a/src/docker/reconcile.rs +++ b/src/docker/reconcile.rs @@ -55,50 +55,6 @@ pub(crate) fn generated_id(agent_id: &str, service_key: &str) -> String { format!("docker-{readable}-{suffix}") } -fn legacy_docker_name(service: &Service) -> Option { - let (base, port) = if let Some(rest) = service.key.strip_prefix("compose:") { - let (path, port) = rest.rsplit_once(':')?; - let mut parts = path.split('/'); - let project = parts.next()?; - let app = parts.next()?; - let replica = parts.next()?; - if parts.next().is_some() { return None; } - let mut base = format!("{project}-{app}"); - if replica != "1" { base.push('-'); base.push_str(replica); } - (base, port) - } else { - let rest = service.key.strip_prefix("container:")?; - let (name, port) = rest.rsplit_once(':')?; - (name.to_owned(), port) - }; - let (port, protocol) = port.split_once('/')?; - if protocol != "tcp" { return None; } - let source = format!("{base}-{port}").to_ascii_lowercase(); - let mut name = String::new(); - let mut dash = false; - for ch in source.chars() { - if ch.is_ascii_lowercase() || ch.is_ascii_digit() { - name.push(ch); - dash = false; - } else if !name.is_empty() && !dash { - name.push('-'); - dash = true; - } - } - let name = name.trim_matches('-'); - Some(name.chars().take(48).collect::().trim_matches('-').to_owned()) -} - -fn effective_assignment(assignment: &Assignment, inventory: Option<&Inventory>) -> Assignment { - let mut result = assignment.clone(); - if let Some(service) = inventory.and_then(|inventory| inventory.services.iter().find(|service| service.key == assignment.service_key)) { - if legacy_docker_name(service).as_deref() == Some(assignment.hostname.as_str()) { - result.hostname = service.technical_name.clone(); - } - } - result -} - pub fn effective_config( mut desired: crate::config::Config, observed: &BTreeMap, @@ -117,7 +73,6 @@ pub fn effective_config( .iter() .filter(|assignment| assignment.enabled) { - let assignment = effective_assignment(assignment, inventory); let hosts = assignment_hosts(&assignment, &agent.base_domain)?; let target = inventory .and_then(|inventory| {