From: Paul Donald Date: Thu, 14 May 2026 11:56:22 +0000 (+0300) Subject: luci-app-dockerman: fixes X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=145f7e1bcef8198cb3585c0239530b9008239213;p=openwrt-luci.git luci-app-dockerman: fixes - fill network selection when clicking container net "connect" - provide container ID for net dis/connect - correct net link in network overview - proper split of arguments in CMD - harden API endpoint access to ACL - allow stop/kill in restarting state - show IP(v4) from built-in networks Signed-off-by: Serhii Ivanov Signed-off-by: Paul Donald --- diff --git a/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js b/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js index 1c5604a643..88c14b0d5e 100644 --- a/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js +++ b/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js @@ -306,7 +306,7 @@ return dm2.dv.extend({ Name: name, NetworkID: netid, DNSNames: net?.DNSNames || '', - IPv4Address: net?.IPAMConfig?.IPv4Address || '', + IPv4Address: net?.IPAMConfig?.IPv4Address || net?.IPAddress || '', IPv6Address: net?.IPAMConfig?.IPv6Address || '', }); } @@ -315,6 +315,7 @@ return dm2.dv.extend({ }, render([this_container, images, networks, cpus_mem, ps_top, stats_data, changes_data]) { + this.networks = networks; const view = this; const containerName = this_container.Name?.substring(1) || this_container.Id || ''; const containerIdShort = (this_container.Id || '').substring(0, 12); @@ -359,7 +360,7 @@ return dm2.dv.extend({ } // Stop button - if (containerStatus === 'running' || containerStatus === 'paused') { + if (containerStatus === 'running' || containerStatus === 'paused' || containerStatus === 'restarting') { const stopBtn = E('button', { 'class': 'cbi-button cbi-button-reset', 'click': (ev) => this.executeAction(ev, 'stop', this_container.Id) @@ -368,7 +369,7 @@ return dm2.dv.extend({ } // Kill button - if (containerStatus === 'running') { + if (containerStatus === 'running' || containerStatus === 'restarting') { const killBtn = E('button', { 'class': 'cbi-button', 'style': 'background-color: #dc3545;', @@ -1849,7 +1850,7 @@ return dm2.dv.extend({ dm2.network_disconnect, { id: networkID, - body: { Container: view.containerId, Force: false } + body: { Container: this_container.Id, Force: false } }, _('Disconnect network'), { @@ -1927,7 +1928,7 @@ return dm2.dv.extend({ ui.hideModal(); - const body = { Container: view.containerId }; + const body = { Container: this_container.Id }; body.EndpointConfig = { IPAMConfig: { IPv4Address: ip4Address } }; //, IPv6Address: ip6Address || null view.executeDockerAction( diff --git a/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js b/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js index d624ec0e50..b919004766 100644 --- a/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js +++ b/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js @@ -142,7 +142,12 @@ return dm2.dv.extend({ } return ports; })(), - command: c.Config?.Cmd ? c.Config?.Cmd.join(' ') : '', + command: c.Config?.Cmd ? c.Config?.Cmd.map(arg => { + if (arg.includes(' ') || arg.includes('"') || arg.includes("'")) { + return '"' + arg.replace(/"/g, '\\"') + '"'; + } + return arg; + }).join(' ') : '', hostname: c.Config?.Hostname || '', publish_all: hostConfig.PublishAllPorts ? 1 : 0, device: (hostConfig.Devices || []).map(d => d.PathOnHost + ':' + d.PathInContainer + (d.CgroupPermissions ? ':' + d.CgroupPermissions : '')), @@ -772,7 +777,7 @@ return dm2.dv.extend({ Tty: toBool(get('tty')), OpenStdin: toBool(get('interactive')), Env: get('env'), - Cmd: command ? command.split(' ') : null, + Cmd: command ? (command.match(/(?:[^\s"]+|"[^"]*")+/g) || []).map(arg => arg.replace(/^"|"$/g, '')) : null, Image: get('image'), HostConfig: { CpuShares: toInt(get('cpu_shares')), diff --git a/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js b/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js index e118ac4f52..ec0499bb84 100644 --- a/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js +++ b/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js @@ -177,6 +177,7 @@ return dm2.dv.extend({ buildContainerActions(cont, idx) { const view = this; const isRunning = cont?.State === 'running'; + const isRestarting = cont?.State === 'restarting'; const isPaused = cont?.State === 'paused'; const btns = [ E('button', { @@ -252,7 +253,7 @@ return dm2.dv.extend({ dm2.Types['container'].sub['stop'].i18n, {showOutput: true, showSuccess: false} ), - 'disabled' : !(isRunning || isPaused) ? true : null + 'disabled' : !(isRunning || isPaused || isRestarting) ? true : null }, [dm2.Types['container'].sub['stop'].e]), E('button', { @@ -264,7 +265,7 @@ return dm2.dv.extend({ dm2.Types['container'].sub['kill'].i18n, {showOutput: true, showSuccess: false} ), - 'disabled' : !(isRunning || isPaused) ? true : null + 'disabled' : !(isRunning || isPaused || isRestarting) ? true : null }, [dm2.Types['container'].sub['kill'].e]), E('button', { diff --git a/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js b/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js index b8638edfed..62a16722d1 100644 --- a/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js +++ b/applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js @@ -208,7 +208,7 @@ return dm2.dv.extend({ const n = net.Name; const _shortId = (net.Id || '').substring(0, 12); const shortLink = E('a', { - 'href': `${view.dockerman_url}/network/${net.Id}`, + 'href': `${this.dockerman_url}/network/${net.Id}`, 'style': 'font-family: monospace;', 'title': _('Click to view this network'), }, [_shortId]); diff --git a/applications/luci-app-dockerman/root/usr/share/luci/menu.d/luci-app-dockerman.json b/applications/luci-app-dockerman/root/usr/share/luci/menu.d/luci-app-dockerman.json index 0cc3995d15..9fa0e7e105 100644 --- a/applications/luci-app-dockerman/root/usr/share/luci/menu.d/luci-app-dockerman.json +++ b/applications/luci-app-dockerman/root/usr/share/luci/menu.d/luci-app-dockerman.json @@ -21,6 +21,9 @@ "action": { "type": "view", "path": "dockerman/overview" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -30,6 +33,9 @@ "action": { "type": "view", "path": "dockerman/configuration" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -37,6 +43,9 @@ "action": { "type": "alias", "path": "admin/services/dockerman/containers" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -49,6 +58,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -61,6 +73,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -73,6 +88,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -81,6 +99,9 @@ "action": { "type": "view", "path": "dockerman/container" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -90,6 +111,9 @@ "action": { "type": "view", "path": "dockerman/containers" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -103,6 +127,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -110,6 +137,9 @@ "action": { "type": "alias", "path": "admin/services/dockerman/containers" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -118,6 +148,9 @@ "action": { "type": "view", "path": "dockerman/container_new" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -131,6 +164,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -144,6 +180,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -156,6 +195,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -169,6 +211,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -182,6 +227,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -204,6 +252,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -217,6 +268,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -224,6 +278,9 @@ "action": { "type": "alias", "path": "admin/services/dockerman/images" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -232,6 +289,9 @@ "action": { "type": "view", "path": "dockerman/network" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -241,6 +301,9 @@ "action": { "type": "view", "path": "dockerman/networks" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -254,6 +317,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -262,6 +328,9 @@ "action": { "type": "view", "path": "dockerman/network_new" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -269,6 +338,9 @@ "action": { "type": "alias", "path": "admin/services/dockerman/networks" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -278,6 +350,9 @@ "action": { "type": "view", "path": "dockerman/volumes" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -291,6 +366,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -304,6 +382,9 @@ "auth": { "methods": [ "cookie:sysauth_https", "cookie:sysauth_http" ], "login": true + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } }, @@ -313,6 +394,9 @@ "action": { "type": "view", "path": "dockerman/events" + }, + "depends": { + "acl": [ "luci-app-dockerman" ] } } } \ No newline at end of file