Merge pull request #4332 from TDT-AG/pr/20200730-luci-app-dockerman

luci-app-dockerman: improvements
This commit is contained in:
Florian Eckert 2020-08-11 12:56:56 +02:00 committed by GitHub
commit d59600cdf6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 50 deletions

View file

@ -12,7 +12,7 @@ function index()
e.dependent = false e.dependent = false
e.acl_depends = { "luci-app-dockerman" } e.acl_depends = { "luci-app-dockerman" }
entry({"admin", "docker", "overview"},cbi("dockerman/overview"),_("Overview"),0).leaf=true entry({"admin", "docker", "overview"},cbi("dockerman/overview"),_("Overview"), 1).leaf=true
local remote = luci.model.uci.cursor():get_bool("dockerd", "globals", "remote_endpoint") local remote = luci.model.uci.cursor():get_bool("dockerd", "globals", "remote_endpoint")
if remote then if remote then
@ -32,11 +32,11 @@ function index()
return return
end end
entry({"admin", "docker", "containers"}, form("dockerman/containers"), _("Containers"),1).leaf=true entry({"admin", "docker", "containers"}, form("dockerman/containers"), _("Containers"), 2).leaf=true
entry({"admin", "docker", "images"}, form("dockerman/images"), _("Images"),2).leaf=true entry({"admin", "docker", "images"}, form("dockerman/images"), _("Images"), 3).leaf=true
entry({"admin", "docker", "networks"}, form("dockerman/networks"), _("Networks"),3).leaf=true entry({"admin", "docker", "networks"}, form("dockerman/networks"), _("Networks"), 4).leaf=true
entry({"admin", "docker", "volumes"}, form("dockerman/volumes"), _("Volumes"),4).leaf=true entry({"admin", "docker", "volumes"}, form("dockerman/volumes"), _("Volumes"), 5).leaf=true
entry({"admin", "docker", "events"}, call("action_events"), _("Events"),5) entry({"admin", "docker", "events"}, call("action_events"), _("Events"), 6)
entry({"admin", "docker", "newcontainer"}, form("dockerman/newcontainer")).leaf=true entry({"admin", "docker", "newcontainer"}, form("dockerman/newcontainer")).leaf=true
entry({"admin", "docker", "newnetwork"}, form("dockerman/newnetwork")).leaf=true entry({"admin", "docker", "newnetwork"}, form("dockerman/newnetwork")).leaf=true
@ -64,12 +64,24 @@ function action_events()
if events.code == 200 then if events.code == 200 then
for _, v in ipairs(events.body) do for _, v in ipairs(events.body) do
local date = "unknown"
if v and v.time then
date = os.date("%Y-%m-%d %H:%M:%S", v.time)
end
local name = v.Actor.Attributes.name or "unknown"
local action = v.Action or "unknown"
if v and v.Type == "container" then if v and v.Type == "container" then
logs = (logs ~= "" and (logs .. "\n") or logs) .. "[" .. os.date("%Y-%m-%d %H:%M:%S", v.time) .."] "..v.Type.. " " .. (v.Action or "null") .. " Container ID:".. (v.Actor.ID or "null") .. " Container Name:" .. (v.Actor.Attributes.name or "null") local id = v.Actor.ID or "unknown"
logs = logs .. string.format("[%s] %s %s Container ID: %s Container Name: %s\n", date, v.Type, action, id, name)
elseif v.Type == "network" then elseif v.Type == "network" then
logs = (logs ~= "" and (logs .. "\n") or logs) .. "[" .. os.date("%Y-%m-%d %H:%M:%S", v.time) .."] "..v.Type.. " " .. v.Action .. " Container ID:"..( v.Actor.Attributes.container or "null" ) .. " Network Name:" .. (v.Actor.Attributes.name or "null") .. " Network type:".. v.Actor.Attributes.type or "" local container = v.Actor.Attributes.container or "unknown"
local network = v.Actor.Attributes.type or "unknown"
logs = logs .. string.format("[%s] %s %s Container ID: %s Network Name: %s Network type: %s\n", date, v.Type, action, container, name, network)
elseif v.Type == "image" then elseif v.Type == "image" then
logs = (logs ~= "" and (logs .. "\n") or logs) .. "[" .. os.date("%Y-%m-%d %H:%M:%S", v.time) .."] "..v.Type.. " " .. v.Action .. " Image:".. (v.Actor.ID or "null").. " Image Name:" .. (v.Actor.Attributes.name or "null") local id = v.Actor.ID or "unknown"
logs = logs .. string.format("[%s] %s %s Image: %s Image name: %s\n", date, v.Type, action, id, name)
end end
end end
end end

View file

@ -704,11 +704,14 @@ elseif action == "console" then
return return
end end
local kill_ttyd = 'netstat -lnpt | grep ":7682[ \t].*ttyd$" | awk \'{print $NF}\' | awk -F\'/\' \'{print "kill -9 " $1}\' | sh > /dev/null' local pid = luci.util.trim(luci.util.exec("netstat -lnpt | grep :7682 | grep ttyd | tr -s ' ' | cut -d ' ' -f7 | cut -d'/' -f1"))
luci.util.exec(kill_ttyd) if pid and pid ~= "" then
luci.util.exec("kill -9 " .. pid)
end
local hosts local hosts
local uci = (require "luci.model.uci").cursor() local uci = require "luci.model.uci".cursor()
local remote = uci:get_bool("dockerd", "globals", "remote_endpoint") local remote = uci:get_bool("dockerd", "globals", "remote_endpoint") or false
local host = nil local host = nil
local port = nil local port = nil
local socket = nil local socket = nil
@ -717,18 +720,25 @@ elseif action == "console" then
host = uci:get("dockerd", "globals", "remote_host") or nil host = uci:get("dockerd", "globals", "remote_host") or nil
port = uci:get("dockerd", "globals", "remote_port") or nil port = uci:get("dockerd", "globals", "remote_port") or nil
else else
socket = uci:get("dockerd", "globals", "socket_path") or nil socket = uci:get("dockerd", "globals", "socket_path") or "/var/run/docker.sock"
end end
if remote and host and port then if remote and host and port then
hosts = host .. ':'.. port hosts = host .. ':'.. port
elseif socket_path then elseif socket then
hosts = socket_path hosts = socket
else else
return return
end end
local start_cmd = cmd_ttyd .. ' -d 2 --once -p 7682 '.. cmd_docker .. ' -H "'.. hosts ..'" exec -it ' .. (uid and uid ~= "" and (" -u ".. uid .. ' ') or "").. container_id .. ' ' .. cmd .. ' &' if uid and uid ~= "" then
uid = "-u " .. uid
else
uid = ""
end
local start_cmd = string.format('%s -d 2 --once -p 7682 %s -H "unix://%s" exec -it %s %s %s&', cmd_ttyd, cmd_docker, hosts, uid, container_id, cmd)
os.execute(start_cmd) os.execute(start_cmd)
o = s:option(DummyValue, "console") o = s:option(DummyValue, "console")

View file

@ -45,13 +45,12 @@ function get_containers()
end end
for i, v in ipairs(containers) do for i, v in ipairs(containers) do
local index = v.Created .. v.Id local index = v.Id
data[index]={} data[index]={}
data[index]["_selected"] = 0 data[index]["_selected"] = 0
data[index]["_id"] = v.Id:sub(1,12) data[index]["_id"] = v.Id:sub(1,12)
data[index]["name"] = v.Names[1]:sub(2) data[index]["_name"] = v.Names[1]:sub(2)
data[index]["_name"] = '<a href='..luci.dispatcher.build_url("admin/docker/container/"..v.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. v.Names[1]:sub(2).."</a>"
data[index]["_status"] = v.Status data[index]["_status"] = v.Status
if v.Status:find("^Up") then if v.Status:find("^Up") then
@ -104,7 +103,11 @@ if s.err then
end end
s = m:section(Table, container_list, translate("Containers")) s = m:section(Table, container_list, translate("Containers"))
s.nodescr=true s.addremove = false
s.sectionhead = translate("Containers")
s.sortable = false
s.template = "cbi/tblsection"
s.extedit = luci.dispatcher.build_url("admin", "docker", "container","%s")
o = s:option(Flag, "_selected","") o = s:option(Flag, "_selected","")
o.disabled = 0 o.disabled = 0
@ -142,7 +145,7 @@ local start_stop_remove = function(m,cmd)
for k in pairs(container_list) do for k in pairs(container_list) do
if container_list[k]._selected == 1 then if container_list[k]._selected == 1 then
container_selected[#container_selected + 1] = container_list[k].name container_selected[#container_selected + 1] = container_list[k]._name
end end
end end
@ -175,7 +178,7 @@ s.rowcolors=false
s.template="cbi/nullsection" s.template="cbi/nullsection"
o = s:option(Button, "_new") o = s:option(Button, "_new")
o.inputtitle= translate("New") o.inputtitle= translate("Add")
o.template = "dockerman/cbi/inlinebutton" o.template = "dockerman/cbi/inlinebutton"
o.inputstyle = "add" o.inputstyle = "add"
o.forcewrite = true o.forcewrite = true

View file

@ -24,41 +24,41 @@ s = m:section(SimpleSection, translate("New Network"))
s.addremove = true s.addremove = true
s.anonymous = true s.anonymous = true
o = s:option(Value, "name", translate("Network Name")) o = s:option(Value, "name",
translate("Network Name"),
translate("Name of the network that can be selected during container creation"))
o.rmempty = true o.rmempty = true
o = s:option(ListValue, "dirver", translate("Driver")) o = s:option(ListValue, "driver", translate("Driver"))
o.rmempty = true o.rmempty = true
o:value("bridge", "bridge") o:value("bridge", translate("Bridge device"))
o:value("macvlan", "macvlan") o:value("macvlan", translate("MAC VLAN"))
o:value("ipvlan", "ipvlan") o:value("ipvlan", translate("IP VLAN"))
o:value("overlay", "overlay") o:value("overlay", translate("Overlay network"))
o = s:option(Value, "parent", translate("Parent Interface")) o = s:option(Value, "parent", translate("Base device"))
o.rmempty = true o.rmempty = true
o:depends("dirver", "macvlan") o:depends("driver", "macvlan")
local interfaces = luci.sys and luci.sys.net and luci.sys.net.devices() or {} local interfaces = luci.sys and luci.sys.net and luci.sys.net.devices() or {}
for _, v in ipairs(interfaces) do for _, v in ipairs(interfaces) do
o:value(v, v) o:value(v, v)
end end
o.default="br-lan"
o.placeholder="br-lan"
o = s:option(Value, "macvlan_mode", translate("Macvlan Mode")) o = s:option(ListValue, "macvlan_mode", translate("Mode"))
o.rmempty = true o.rmempty = true
o:depends("dirver", "macvlan") o:depends("driver", "macvlan")
o.default="bridge" o.default="bridge"
o:value("bridge", "bridge") o:value("bridge", translate("Bridge (Support direct communication between MAC VLANs)"))
o:value("private", "private") o:value("private", translate("Private (Prevent communication between MAC VLANs)"))
o:value("vepa", "vepa") o:value("vepa", translate("VEPA (Virtual Ethernet Port Aggregator)"))
o:value("passthru", "passthru") o:value("passthru", translate("Pass-through (Mirror physical device to single MAC VLAN)"))
o = s:option(Value, "ipvlan_mode", translate("Ipvlan Mode")) o = s:option(ListValue, "ipvlan_mode", translate("Ipvlan Mode"))
o.rmempty = true o.rmempty = true
o:depends("dirver", "ipvlan") o:depends("driver", "ipvlan")
o.default="l3" o.default="l3"
o:value("l2", "l2") o:value("l2", translate("L2 bridge"))
o:value("l3", "l3") o:value("l3", translate("L3 bridge"))
o = s:option(Flag, "ingress", o = s:option(Flag, "ingress",
translate("Ingress"), translate("Ingress"),
@ -67,7 +67,7 @@ o.rmempty = true
o.disabled = 0 o.disabled = 0
o.enabled = 1 o.enabled = 1
o.default = 0 o.default = 0
o:depends("dirver", "overlay") o:depends("driver", "overlay")
o = s:option(DynamicList, "options", translate("Options")) o = s:option(DynamicList, "options", translate("Options"))
o.rmempty = true o.rmempty = true
@ -75,14 +75,14 @@ o.placeholder="com.docker.network.driver.mtu=1500"
o = s:option(Flag, "internal", translate("Internal"), translate("Restrict external access to the network")) o = s:option(Flag, "internal", translate("Internal"), translate("Restrict external access to the network"))
o.rmempty = true o.rmempty = true
o:depends("dirver", "overlay") o:depends("driver", "overlay")
o.disabled = 0 o.disabled = 0
o.enabled = 1 o.enabled = 1
o.default = 0 o.default = 0
if nixio.fs.access("/etc/config/network") and nixio.fs.access("/etc/config/firewall")then if nixio.fs.access("/etc/config/network") and nixio.fs.access("/etc/config/firewall")then
o = s:option(Flag, "op_macvlan", translate("Create macvlan interface"), translate("Auto create macvlan interface in Openwrt")) o = s:option(Flag, "op_macvlan", translate("Create macvlan interface"), translate("Auto create macvlan interface in Openwrt"))
o:depends("dirver", "macvlan") o:depends("driver", "macvlan")
o.disabled = 0 o.disabled = 0
o.enabled = 1 o.enabled = 1
o.default = 1 o.default = 1
@ -128,7 +128,7 @@ o:depends("ipv6", 1)
m.handle = function(self, state, data) m.handle = function(self, state, data)
if state == FORM_VALID then if state == FORM_VALID then
local name = data.name local name = data.name
local driver = data.dirver local driver = data.driver
local internal = data.internal == 1 and true or false local internal = data.internal == 1 and true or false

View file

@ -99,8 +99,8 @@ o.rmempty = false
o = s:option(Value, "socket_path", o = s:option(Value, "socket_path",
translate("Docker Socket Path")) translate("Docker Socket Path"))
o.default = "unix://var/run/docker.sock" o.default = "unix:///var/run/docker.sock"
o.placeholder = "unix://var/run/docker.sock" o.placeholder = "unix:///var/run/docker.sock"
o:depends("remote_endpoint", 1) o:depends("remote_endpoint", 1)
o = s:option(Value, "remote_host", o = s:option(Value, "remote_host",
@ -146,7 +146,7 @@ if nixio.fs.access("/usr/bin/dockerd") then
o = s:option(DynamicList, "hosts", o = s:option(DynamicList, "hosts",
translate("Client connection"), translate("Client connection"),
translate('Specifies where the Docker daemon will listen for client connections')) translate('Specifies where the Docker daemon will listen for client connections'))
o:value("unix://var/run/docker.sock", "unix://var/run/docker.sock") o:value("unix:///var/run/docker.sock", "unix:///var/run/docker.sock")
o:value("tcp://0.0.0.0:2375", "tcp://0.0.0.0:2375") o:value("tcp://0.0.0.0:2375", "tcp://0.0.0.0:2375")
o.rmempty = true o.rmempty = true
o:depends("remote_endpoint", 0) o:depends("remote_endpoint", 0)