From 3d47eab13ff89e2807fbfa4b970b8a2b5db5d356 Mon Sep 17 00:00:00 2001 From: kiddin9 <48883331+kiddin9@users.noreply.github.com> Date: Fri, 22 May 2026 14:04:24 +0800 Subject: [PATCH] Update dockerman.patch --- .github/diy/patches/dockerman.patch | 154 ---------------------------- 1 file changed, 154 deletions(-) diff --git a/.github/diy/patches/dockerman.patch b/.github/diy/patches/dockerman.patch index 5726c137..0b4d468c 100644 --- a/.github/diy/patches/dockerman.patch +++ b/.github/diy/patches/dockerman.patch @@ -307,157 +307,3 @@ o = s.taboption('globals', form.ListValue, 'log_level', _('Log Level'), - ---- a/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js -+++ b/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js -@@ -73,7 +73,8 @@ return dm2.dv.extend({ - const hostConfig = c.HostConfig || {}; - const resolvedImage = resolveImageId(c.Image) || resolveImageId(c.Config?.Image) || c.Image || c.Config?.Image || ''; - const builtInNetworks = new Set(['none', 'bridge', 'host']); -- const [netnames, nets] = Object.entries(c.NetworkSettings?.Networks || {}); -+ // Object.entries returns [[name, obj], ...] — pick the first network -+ const [[firstName, firstNet] = []] = Object.entries(c.NetworkSettings?.Networks || {}); - - containerData.container = { - name: c.Name?.substring(1) || '', -@@ -82,20 +83,18 @@ return dm2.dv.extend({ - image: resolvedImage, - privileged: hostConfig.Privileged ? 1 : 0, - restart_policy: hostConfig.RestartPolicy?.Name || 'unless-stopped', -- network: (() => { -- return (netnames && (netnames.length > 0)) ? netnames[0] : ''; -- })(), -+ network: firstName || '', - ipv4: (() => { -- if (builtInNetworks.has(netnames[0])) return ''; -- return (nets && (nets.length > 0)) ? nets[0]?.IPAddress || '' : ''; -+ if (!firstName || builtInNetworks.has(firstName)) return ''; -+ return firstNet?.IPAddress || ''; - })(), - ipv6: (() => { -- if (builtInNetworks.has(netnames[0])) return ''; -- return (nets && (nets.length > 0)) ? nets[0]?.GlobalIPv6Address || '' : ''; -+ if (!firstName || builtInNetworks.has(firstName)) return ''; -+ return firstNet?.GlobalIPv6Address || ''; - })(), - ipv6_lla: (() => { -- if (builtInNetworks.has(netnames[0])) return ''; -- return (nets && (nets.length > 0)) ? nets[0]?.LinkLocalIPv6Address || '' : ''; -+ if (!firstName || builtInNetworks.has(firstName)) return ''; -+ return firstNet?.LinkLocalIPv6Address || ''; - })(), - link: hostConfig.Links || [], - dns: hostConfig.Dns || [], -@@ -135,9 +134,12 @@ return dm2.dv.extend({ - publish: (() => { - const ports = []; - for (const [containerPort, bindings] of Object.entries(hostConfig.PortBindings || {})) { -- if (Array.isArray(bindings) && bindings.length > 0 && bindings[0]?.HostPort) { -- const hostPort = bindings[0].HostPort; -- ports.push(hostPort + ':' + containerPort); -+ if (Array.isArray(bindings) && bindings.length > 0) { -+ for (const b of bindings) { -+ if (!b?.HostPort) continue; -+ const ip = b.HostIp || ''; -+ ports.push((ip ? ip + ':' : '') + b.HostPort + ':' + containerPort); -+ } - } - } - return ports; -@@ -801,9 +803,15 @@ return dm2.dv.extend({ - (Array.isArray(publish) ? publish : [publish]) - .filter(p => p && typeof p === 'string' && p.trim().length > 0) - .map(p => { -- const m = p.match(/^(\d+):(\d+)\/(tcp|udp)$/); -- if (m) return [`${m[2]}/${m[3]}`, [{ HostPort: m[1] }]]; -- return null; -+ // formats: hostPort:cPort/proto or hostIp:hostPort:cPort/proto -+ const m = p.match(/^(?:([^:]+):(\d+)|(\d+)):(\d+)\/(tcp|udp)$/); -+ if (!m) return null; -+ const hostIp = m[1] || ''; -+ const hostPort = m[2] || m[3]; -+ const cPort = m[4]; -+ const proto = m[5]; -+ const binding = hostIp ? { HostIp: hostIp, HostPort: hostPort } : { HostPort: hostPort }; -+ return [`${cPort}/${proto}`, [binding]]; - }).filter(Boolean) - ) : undefined, - Mounts: undefined, - ---- a/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js -+++ b/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js -@@ -308,6 +308,56 @@ return dm2.dv.extend({ - }, E('div', btns)); - }, - -+ buildPortLinks(ports) { -+ // cont.Ports[] from GET /containers/json — flat array. -+ // Published ports have {IP, PrivatePort, PublicPort, Type}. -+ // Exposed-only ports omit IP and PublicPort: {PrivatePort, Type}. -+ if (!Array.isArray(ports) || ports.length === 0) return ''; -+ -+ const LOCAL_IPS = new Set(['0.0.0.0', '::']); -+ -+ // Sort: published (has PublicPort) before exposed-only, then by PrivatePort -+ const sorted = [...ports].sort((a, b) => { -+ const aHasPub = a.PublicPort ? 1 : 0; -+ const bHasPub = b.PublicPort ? 1 : 0; -+ if (aHasPub !== bHasPub) return bHasPub - aHasPub; -+ return (a.PrivatePort || 0) - (b.PrivatePort || 0); -+ }); -+ -+ const lines = sorted.map(p => { -+ const ip = p.IP || ''; -+ const pub = p.PublicPort || ''; -+ const priv = p.PrivatePort || ''; -+ const type = p.Type || ''; -+ -+ const isIPv6 = ip.includes(':'); -+ const isLocal = LOCAL_IPS.has(ip); -+ const displayIp = isIPv6 ? `[${ip}]` : ip; -+ -+ let label; -+ if (pub && ip) label = `${displayIp}:${pub}->${priv}/${type}`; -+ else if (pub) label = `${pub}->${priv}/${type}`; -+ else label = `${priv}/${type}`; -+ -+ // Clickable link for published TCP ports only -+ if (type === 'tcp' && pub) { -+ const host = isLocal ? window.location.hostname : displayIp; -+ return E('div', {}, [ -+ E('a', { -+ href: `http://${host}:${pub}`, -+ target: '_blank', -+ rel: 'noopener noreferrer', -+ title: _('Open in browser'), -+ }, [label]), -+ ]); -+ } -+ -+ return E('div', {}, [label]); -+ }); -+ -+ return E('div', {}, lines); -+ }, -+ - handleSave: null, - handleSaveApply: null, - handleReset: null, -@@ -342,16 +392,7 @@ return dm2.dv.extend({ - _shortId: (cont?.Id || '').substring(0, 12), - Networks: this.parseNetworkLinksForContainer(network_list, cont?.NetworkSettings?.Networks || {}, true), - Created: this.buildTimeString(cont?.Created) || '', -- Ports: (Array.isArray(cont.Ports) && cont.Ports.length > 0) -- ? cont.Ports.map(p => { -- // const ip = p.IP || ''; -- const pub = p.PublicPort || ''; -- const priv = p.PrivatePort || ''; -- const type = p.Type || ''; -- return `${pub ? pub + ':' : ''}${priv}/${type}`; -- // return `${ip ? ip + ':' : ''}${pub} -> ${priv} (${type})`; -- }).join('
') -- : '', -+ Ports: this.buildPortLinks(cont.Ports), - }); - } -