diff --git a/package/lean/luci-app-dockerman/Makefile b/package/lean/luci-app-dockerman/Makefile old mode 100644 new mode 100755 index 55c7052df..686e4d627 --- a/package/lean/luci-app-dockerman/Makefile +++ b/package/lean/luci-app-dockerman/Makefile @@ -1,18 +1,18 @@ +# +# Copyright (C) 2008-2014 The LuCI Team +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + include $(TOPDIR)/rules.mk -LUCI_TITLE:=Docker Manager interface for LuCI -LUCI_DEPENDS:=+luci-lib-docker +docker-ce +e2fsprogs +fdisk -PKG_NAME:=luci-app-dockerman -PKG_VERSION:=v0.3.0 -PKG_RELEASE:=leanmod-3 -PKG_MAINTAINER:=lisaac -PKG_LICENSE:=AGPL-3.0 +LUCI_TITLE:=Luci for Docker-CE +LUCI_DEPENDS:=+docker-ce +e2fsprogs +fdisk +LUCI_PKGARCH:=all +PKG_VERSION:=1 +PKG_RELEASE:=9 include $(TOPDIR)/feeds/luci/luci.mk -define Package/$(PKG_NAME)/postinst -#!/bin/sh -rm -rf /tmp/luci-indexcache /tmp/luci-modulecache -endef - # call BuildPackage - OpenWrt buildroot signature + diff --git a/package/lean/luci-app-dockerman/luasrc/controller/docker.lua b/package/lean/luci-app-dockerman/luasrc/controller/docker.lua new file mode 100644 index 000000000..93b8f6618 --- /dev/null +++ b/package/lean/luci-app-dockerman/luasrc/controller/docker.lua @@ -0,0 +1,17 @@ +module("luci.controller.docker", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/dockerd") then + return + end + + entry({"admin", "services", "docker"}, cbi("docker"), _("Docker CE Container"), 199).dependent = true + entry({"admin","services","docker","status"},call("act_status")).leaf=true +end + +function act_status() + local e={} + e.running=luci.sys.call("pgrep /usr/bin/dockerd >/dev/null")==0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end \ No newline at end of file diff --git a/package/lean/luci-app-dockerman/luasrc/controller/dockerman.lua b/package/lean/luci-app-dockerman/luasrc/controller/dockerman.lua deleted file mode 100644 index cd8060764..000000000 --- a/package/lean/luci-app-dockerman/luasrc/controller/dockerman.lua +++ /dev/null @@ -1,201 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- -require "luci.util" -local docker = require "luci.model.docker" -local uci = require "luci.model.uci" - -module("luci.controller.dockerman",package.seeall) - -function index() - - entry({"admin", "services","docker"}, firstchild(), "Docker", 40).dependent = false - entry({"admin","services","docker","overview"},cbi("dockerman/overview"),_("Overview"),0).leaf=true - - local socket = luci.model.uci.cursor():get("dockerman", "local", "socket_path") - if not nixio.fs.access(socket) then return end - if (require "luci.model.docker").new():_ping().code ~= 200 then return end - entry({"admin","services","docker","containers"},form("dockerman/containers"),_("Containers"),1).leaf=true - entry({"admin","services","docker","images"},form("dockerman/images"),_("Images"),2).leaf=true - entry({"admin","services","docker","networks"},form("dockerman/networks"),_("Networks"),3).leaf=true - entry({"admin","services","docker","volumes"},form("dockerman/volumes"),_("Volumes"),4).leaf=true - entry({"admin","services","docker","events"},call("action_events"),_("Events"),5) - entry({"admin","services","docker","newcontainer"},form("dockerman/newcontainer")).leaf=true - entry({"admin","services","docker","newnetwork"},form("dockerman/newnetwork")).leaf=true - entry({"admin","services","docker","container"},form("dockerman/container")).leaf=true - entry({"admin","services","docker","container_stats"},call("action_get_container_stats")).leaf=true - entry({"admin","services","docker","container_get_archive"},call("download_archive")).leaf=true - entry({"admin","services","docker","container_put_archive"},call("upload_archive")).leaf=true - entry({"admin","services","docker","confirm"},call("action_confirm")).leaf=true - -end - - -function action_events() - local logs = "" - local dk = docker.new() - local query ={} - query["until"] = os.time() - local events = dk:events({query = query}) - for _, v in ipairs(events.body) do - if 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") - 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 "" - 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") - end - end - luci.template.render("dockerman/logs", {self={syslog = logs, title="Docker Events"}}) -end - -local calculate_cpu_percent = function(d) - if type(d) ~= "table" then return end - cpu_count = tonumber(d["cpu_stats"]["online_cpus"]) - cpu_percent = 0.0 - cpu_delta = tonumber(d["cpu_stats"]["cpu_usage"]["total_usage"]) - tonumber(d["precpu_stats"]["cpu_usage"]["total_usage"]) - system_delta = tonumber(d["cpu_stats"]["system_cpu_usage"]) - tonumber(d["precpu_stats"]["system_cpu_usage"]) - if system_delta > 0.0 then - cpu_percent = string.format("%.2f", cpu_delta / system_delta * 100.0 * cpu_count) - end - -- return cpu_percent .. "%" - return cpu_percent -end - -local get_memory = function(d) - if type(d) ~= "table" then return end - -- local limit = string.format("%.2f", tonumber(d["memory_stats"]["limit"]) / 1024 / 1024) - -- local usage = string.format("%.2f", (tonumber(d["memory_stats"]["usage"]) - tonumber(d["memory_stats"]["stats"]["total_cache"])) / 1024 / 1024) - -- return usage .. "MB / " .. limit.. "MB" - local limit =tonumber(d["memory_stats"]["limit"]) - local usage = tonumber(d["memory_stats"]["usage"]) - tonumber(d["memory_stats"]["stats"]["total_cache"]) - return usage, limit -end - -local get_rx_tx = function(d) - if type(d) ~="table" then return end - -- local data - -- if type(d["networks"]) == "table" then - -- for e, v in pairs(d["networks"]) do - -- data = (data and (data .. "
") or "") .. e .. " Total Tx:" .. string.format("%.2f",(tonumber(v.tx_bytes)/1024/1024)) .. "MB Total Rx: ".. string.format("%.2f",(tonumber(v.rx_bytes)/1024/1024)) .. "MB" - -- end - -- end - local data = {} - if type(d["networks"]) == "table" then - for e, v in pairs(d["networks"]) do - data[e] = { - bw_tx = tonumber(v.tx_bytes), - bw_rx = tonumber(v.rx_bytes) - } - end - end - return data -end - -function action_get_container_stats(container_id) - if container_id then - local dk = docker.new() - local response = dk.containers:inspect({id = container_id}) - if response.code == 200 and response.body.State.Running then - response = dk.containers:stats({id = container_id, query = {stream = false}}) - if response.code == 200 then - local container_stats = response.body - local cpu_percent = calculate_cpu_percent(container_stats) - local mem_useage, mem_limit = get_memory(container_stats) - local bw_rxtx = get_rx_tx(container_stats) - luci.http.status(response.code, response.body.message) - luci.http.prepare_content("application/json") - luci.http.write_json({ - cpu_percent = cpu_percent, - memory = { - mem_useage = mem_useage, - mem_limit = mem_limit - }, - bw_rxtx = bw_rxtx - }) - else - luci.http.status(response.code, response.body.message) - luci.http.prepare_content("text/plain") - luci.http.write(response.body.message) - end - else - if response.code == 200 then - luci.http.status(500, "container "..container_id.." not running") - luci.http.prepare_content("text/plain") - luci.http.write("Container "..container_id.." not running") - else - luci.http.status(response.code, response.body.message) - luci.http.prepare_content("text/plain") - luci.http.write(response.body.message) - end - end - else - luci.http.status(404, "No container name or id") - luci.http.prepare_content("text/plain") - luci.http.write("No container name or id") - end -end - -function action_confirm() - local status_path=luci.model.uci.cursor():get("dockerman", "local", "status_path") - local data = nixio.fs.readfile(status_path) - if data then - code = 202 - msg = data - else - code = 200 - msg = "finish" - data = "finish" - end - -- luci.util.perror(data) - luci.http.status(code, msg) - luci.http.prepare_content("application/json") - luci.http.write_json({info = data}) -end - -function download_archive() - local id = luci.http.formvalue("id") - local path = luci.http.formvalue("path") - local dk = docker.new() - local first - - local cb = function(res, chunk) - if res.code == 200 then - if not first then - first = true - luci.http.header('Content-Disposition', 'inline; filename="archive.tar"') - luci.http.header('Content-Type', 'application\/x-tar') - end - luci.ltn12.pump.all(chunk, luci.http.write) - else - if not first then - first = true - luci.http.prepare_content("text/plain") - end - luci.ltn12.pump.all(chunk, luci.http.write) - end - end - - local res = dk.containers:get_archive({id = id, query = {path = path}}, cb) -end - -function upload_archive(container_id) - local path = luci.http.formvalue("upload-path") - local dk = docker.new() - local ltn12 = require "luci.ltn12" - - rec_send = function(sinkout) - luci.http.setfilehandler(function (meta, chunk, eof) - if chunk then - ltn12.pump.step(ltn12.source.string(chunk), sinkout) - end - end) - end - - local res = dk.containers:put_archive({id = container_id, query = {path = path}, body = rec_send}) - local msg = res and res.body and res.body.message or nil - luci.http.status(res.code, msg) - luci.http.prepare_content("application/json") - luci.http.write_json({message = msg}) -end diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/docker.lua new file mode 100644 index 000000000..270fecbbc --- /dev/null +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/docker.lua @@ -0,0 +1,23 @@ +local running = (luci.sys.call("pidof portainer >/dev/null") == 0) +local button = "" + +if running then + button = "      


" +end + +m = Map("dockerd", "Docker CE", translate("Docker is a set of platform-as-a-service (PaaS) products that use OS-level virtualization to deliver software in packages called containers.") .. button) + + +m:section(SimpleSection).template = "docker/docker_status" + +s = m:section(TypedSection, "docker") +s.anonymous = true + +wan_mode = s:option(Flag, "wan_mode", translate("Enable WAN access Dokcer"), translate("Enable WAN access docker mapped ports")) +wan_mode.default = 0 +wan_mode.rmempty = false + +o=s:option(DummyValue,"readme",translate(" ")) +o.description=translate(""..translate("Download DockerReadme.pdf").."") + +return m \ No newline at end of file diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua deleted file mode 100644 index fbb87615d..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua +++ /dev/null @@ -1,488 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -local uci = luci.model.uci.cursor() -local docker = require "luci.model.docker" -local dk = docker.new() -container_id = arg[1] -local action = arg[2] or "info" - -local images, networks, containers_info -if not container_id then return end -local res = dk.containers:inspect({id = container_id}) -if res.code < 300 then container_info = res.body else return end -res = dk.networks:list() -if res.code < 300 then networks = res.body else return end - -local get_ports = function(d) - local data - if d.HostConfig and d.HostConfig.PortBindings then - for inter, out in pairs(d.HostConfig.PortBindings) do - data = (data and (data .. "
") or "") .. out[1]["HostPort"] .. ":" .. inter - end - end - return data -end - -local get_env = function(d) - local data - if d.Config and d.Config.Env then - for _,v in ipairs(d.Config.Env) do - data = (data and (data .. "
") or "") .. v - end - end - return data -end - -local get_command = function(d) - local data - if d.Config and d.Config.Cmd then - for _,v in ipairs(d.Config.Cmd) do - data = (data and (data .. " ") or "") .. v - end - end - return data -end - -local get_mounts = function(d) - local data - if d.Mounts then - for _,v in ipairs(d.Mounts) do - local v_sorce_d, v_dest_d - local v_sorce = "" - local v_dest = "" - for v_sorce_d in v["Source"]:gmatch('[^/]+') do - if v_sorce_d and #v_sorce_d > 12 then - v_sorce = v_sorce .. "/" .. v_sorce_d:sub(1,12) .. "..." - else - v_sorce = v_sorce .."/".. v_sorce_d - end - end - for v_dest_d in v["Destination"]:gmatch('[^/]+') do - if v_dest_d and #v_dest_d > 12 then - v_dest = v_dest .. "/" .. v_dest_d:sub(1,12) .. "..." - else - v_dest = v_dest .."/".. v_dest_d - end - end - data = (data and (data .. "
") or "") .. v_sorce .. ":" .. v["Destination"] .. (v["Mode"] ~= "" and (":" .. v["Mode"]) or "") - end - end - return data -end - -local get_device = function(d) - local data - if d.HostConfig and d.HostConfig.Devices then - for _,v in ipairs(d.HostConfig.Devices) do - data = (data and (data .. "
") or "") .. v["PathOnHost"] .. ":" .. v["PathInContainer"] .. (v["CgroupPermissions"] ~= "" and (":" .. v["CgroupPermissions"]) or "") - end - end - return data -end - -local get_links = function(d) - local data - if d.HostConfig and d.HostConfig.Links then - for _,v in ipairs(d.HostConfig.Links) do - data = (data and (data .. "
") or "") .. v - end - end - return data -end - -local get_networks = function(d) - local data={} - if d.NetworkSettings and d.NetworkSettings.Networks and type(d.NetworkSettings.Networks) == "table" then - for k,v in pairs(d.NetworkSettings.Networks) do - data[k] = v.IPAddress or "" - end - end - return data -end - - -local start_stop_remove = function(m, cmd) - docker:clear_status() - docker:append_status("Containers: " .. cmd .. " " .. container_id .. "...") - local res - if cmd ~= "upgrade" then - res = dk.containers[cmd](dk, {id = container_id}) - else - res = dk.containers_upgrade(dk, {id = container_id}) - end - if res and res.code >= 300 then - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/container/"..container_id)) - else - docker:clear_status() - if cmd ~= "remove" and cmd ~= "upgrade" then - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/container/"..container_id)) - else - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/containers")) - end - end -end - -m=SimpleForm("docker", container_info.Name:sub(2), translate("Docker Container") ) -m.template = "dockerman/cbi/xsimpleform" -m.redirect = luci.dispatcher.build_url("admin/services/docker/containers") --- m:append(Template("dockerman/container")) -docker_status = m:section(SimpleSection) -docker_status.template = "dockerman/apply_widget" -docker_status.err=nixio.fs.readfile(dk.options.status_path) --- luci.util.perror(docker_status.err) -if docker_status.err then docker:clear_status() end - - -action_section = m:section(Table,{{}}) -action_section.notitle=true -action_section.rowcolors=false -action_section.template = "cbi/nullsection" - -btnstart=action_section:option(Button, "_start") -btnstart.template = "dockerman/cbi/inlinebutton" -btnstart.inputtitle=translate("Start") -btnstart.inputstyle = "apply" -btnstart.forcewrite = true -btnrestart=action_section:option(Button, "_restart") -btnrestart.template = "dockerman/cbi/inlinebutton" -btnrestart.inputtitle=translate("Restart") -btnrestart.inputstyle = "reload" -btnrestart.forcewrite = true -btnstop=action_section:option(Button, "_stop") -btnstop.template = "dockerman/cbi/inlinebutton" -btnstop.inputtitle=translate("Stop") -btnstop.inputstyle = "reset" -btnstop.forcewrite = true -btnupgrade=action_section:option(Button, "_upgrade") -btnupgrade.template = "dockerman/cbi/inlinebutton" -btnupgrade.inputtitle=translate("Upgrade") -btnupgrade.inputstyle = "reload" -btnstop.forcewrite = true -btnduplicate=action_section:option(Button, "_duplicate") -btnduplicate.template = "dockerman/cbi/inlinebutton" -btnduplicate.inputtitle=translate("Duplicate") -btnduplicate.inputstyle = "add" -btnstop.forcewrite = true -btnremove=action_section:option(Button, "_remove") -btnremove.template = "dockerman/cbi/inlinebutton" -btnremove.inputtitle=translate("Remove") -btnremove.inputstyle = "remove" -btnremove.forcewrite = true - -btnstart.write = function(self, section) - start_stop_remove(m,"start") -end -btnrestart.write = function(self, section) - start_stop_remove(m,"restart") -end -btnupgrade.write = function(self, section) - start_stop_remove(m,"upgrade") -end -btnremove.write = function(self, section) - start_stop_remove(m,"remove") -end -btnstop.write = function(self, section) - start_stop_remove(m,"stop") -end -btnduplicate.write = function(self, section) - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newcontainer/duplicate/"..container_id)) -end - -tab_section = m:section(SimpleSection) -tab_section.template = "dockerman/container" - -if action == "info" then - m.submit = false - m.reset = false - table_info = { - ["01name"] = {_key = translate("Name"), _value = container_info.Name:sub(2) or "-", _button=translate("Update")}, - ["02id"] = {_key = translate("ID"), _value = container_info.Id or "-"}, - ["03image"] = {_key = translate("Image"), _value = container_info.Config.Image .. "
" .. container_info.Image}, - ["04status"] = {_key = translate("Status"), _value = container_info.State and container_info.State.Status or "-"}, - ["05created"] = {_key = translate("Created"), _value = container_info.Created or "-"}, - } - table_info["06start"] = container_info.State.Status == "running" and {_key = translate("Start Time"), _value = container_info.State and container_info.State.StartedAt or "-"} or {_key = translate("Finish Time"), _value = container_info.State and container_info.State.FinishedAt or "-"} - table_info["07healthy"] = {_key = translate("Healthy"), _value = container_info.State and container_info.State.Health and container_info.State.Health.Status or "-"} - table_info["08restart"] = {_key = translate("Restart Policy"), _value = container_info.HostConfig and container_info.HostConfig.RestartPolicy and container_info.HostConfig.RestartPolicy.Name or "-", _button=translate("Update")} - table_info["09device"] = {_key = translate("Device"), _value = get_device(container_info) or "-"} - table_info["09mount"] = {_key = translate("Mount/Volume"), _value = get_mounts(container_info) or "-"} - - table_info["10cmd"] = {_key = translate("Command"), _value = get_command(container_info) or "-"} - table_info["11env"] = {_key = translate("Env"), _value = get_env(container_info) or "-"} - table_info["12ports"] = {_key = translate("Ports"), _value = get_ports(container_info) or "-"} - table_info["13links"] = {_key = translate("Links"), _value = get_links(container_info) or "-"} - info_networks = get_networks(container_info) - list_networks = {} - for _, v in ipairs (networks) do - if v.Name then - local parent = v.Options and v.Options.parent or nil - local ip = v.IPAM and v.IPAM.Config and v.IPAM.Config[1] and v.IPAM.Config[1].Subnet or nil - ipv6 = v.IPAM and v.IPAM.Config and v.IPAM.Config[2] and v.IPAM.Config[2].Subnet or nil - local network_name = v.Name .. " | " .. v.Driver .. (parent and (" | " .. parent) or "") .. (ip and (" | " .. ip) or "").. (ipv6 and (" | " .. ipv6) or "") - list_networks[v.Name] = network_name - end - end - - if type(info_networks)== "table" then - for k,v in pairs(info_networks) do - table_info["14network"..k] = { - _key = translate("Network"), _value = k.. (v~="" and (" | ".. v) or ""), _button=translate("Disconnect") - } - list_networks[k]=nil - end - end - - table_info["15connect"] = {_key = translate("Connect Network"), _value = list_networks ,_opts = "", _button=translate("Connect")} - - - d_info = m:section(Table,table_info) - d_info.nodescr=true - d_info.formvalue=function(self, section) - return table_info - end - dv_key = d_info:option(DummyValue, "_key", translate("Info")) - dv_key.width = "20%" - dv_value = d_info:option(ListValue, "_value") - dv_value.render = function(self, section, scope) - if table_info[section]._key == translate("Name") then - self:reset_values() - self.template = "cbi/value" - self.size = 30 - self.keylist = {} - self.vallist = {} - self.default=table_info[section]._value - Value.render(self, section, scope) - elseif table_info[section]._key == translate("Restart Policy") then - self.template = "cbi/lvalue" - self:reset_values() - self.size = nil - self:value("no", "No") - self:value("unless-stopped", "Unless stopped") - self:value("always", "Always") - self:value("on-failure", "On failure") - self.default=table_info[section]._value - ListValue.render(self, section, scope) - elseif table_info[section]._key == translate("Connect Network") then - self.template = "cbi/lvalue" - self:reset_values() - self.size = nil - for k,v in pairs(list_networks) do - self:value(k,v) - end - self.default=table_info[section]._value - ListValue.render(self, section, scope) - else - self:reset_values() - self.rawhtml=true - self.template = "cbi/dvalue" - self.default=table_info[section]._value - DummyValue.render(self, section, scope) - end - end - dv_value.forcewrite = true -- for write function using simpleform - dv_value.write = function(self, section, value) - table_info[section]._value=value - end - dv_value.validate = function(self, value) - return value - end - dv_opts = d_info:option(Value, "_opts") - dv_opts.forcewrite = true -- for write function using simpleform - dv_opts.write = function(self, section, value) - - table_info[section]._opts=value - end - dv_opts.validate = function(self, value) - return value - end - dv_opts.render = function(self, section, scope) - if table_info[section]._key==translate("Connect Network") then - self.template = "cbi/value" - self.keylist = {} - self.vallist = {} - self.placeholder = "10.1.1.254" - self.datatype = "ip4addr" - self.default=table_info[section]._opts - Value.render(self, section, scope) - else - self.rawhtml=true - self.template = "cbi/dvalue" - self.default=table_info[section]._opts - DummyValue.render(self, section, scope) - end - end - btn_update = d_info:option(Button, "_button") - btn_update.forcewrite = true - btn_update.render = function(self, section, scope) - if table_info[section]._button and table_info[section]._value ~= nil then - btn_update.inputtitle=table_info[section]._button - self.template = "cbi/button" - Button.render(self, section, scope) - else - self.template = "dockerman/cbi/dummyvalue" - self.default="" - DummyValue.render(self, section, scope) - end - end - btn_update.write = function(self, section, value) - -- luci.util.perror(section) - local res - docker:clear_status() - if section == "01name" then - docker:append_status("Containers: rename " .. container_id .. "...") - local new_name = table_info[section]._value - res = dk.containers:rename({id = container_id, query = {name=new_name}}) - elseif section == "08restart" then - docker:append_status("Containers: update " .. container_id .. "...") - local new_restart = table_info[section]._value - res = dk.containers:update({id = container_id, body = {RestartPolicy = {Name = new_restart}}}) - elseif table_info[section]._key == translate("Network") then - local _,_,leave_network = table_info[section]._value:find("(.-) | .+") - leave_network = leave_network or table_info[section]._value - docker:append_status("Network: disconnect " .. leave_network .. container_id .. "...") - res = dk.networks:disconnect({name = leave_network, body = {Container = container_id}}) - elseif section == "15connect" then - local connect_network = table_info[section]._value - local network_opiton - if connect_network ~= "none" and connect_network ~= "bridge" and connect_network ~= "host" then - -- luci.util.perror(table_info[section]._opts) - network_opiton = table_info[section]._opts ~= "" and { - IPAMConfig={ - IPv4Address=table_info[section]._opts - } - } or nil - end - docker:append_status("Network: connect " .. connect_network .. container_id .. "...") - res = dk.networks:connect({name = connect_network, body = {Container = container_id, EndpointConfig= network_opiton}}) - end - if res and res.code > 300 then - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) - else - docker:clear_status() - end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/container/"..container_id.."/info")) - end - --- info end -elseif action == "edit" then - local editsection= m:section(SimpleSection) - d = editsection:option( Value, "cpus", translate("CPUs"), translate("Number of CPUs. Number is a fractional number. 0.000 means no limit.")) - d.placeholder = "1.5" - d.rmempty = true - d.datatype="ufloat" - d.default = container_info.HostConfig.NanoCpus / (10^9) - - d = editsection:option(Value, "cpushares", translate("CPU Shares Weight"), translate("CPU shares relative weight, if 0 is set, the system will ignore the value and use the default of 1024.")) - d.placeholder = "1024" - d.rmempty = true - d.datatype="uinteger" - d.default = container_info.HostConfig.CpuShares - - d = editsection:option(Value, "memory", translate("Memory"), translate("Memory limit (format: []). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M.")) - d.placeholder = "128m" - d.rmempty = true - d.default = container_info.HostConfig.Memory ~=0 and ((container_info.HostConfig.Memory / 1024 /1024) .. "M") or 0 - - d = editsection:option(Value, "blkioweight", translate("Block IO Weight"), translate("Block IO weight (relative weight) accepts a weight value between 10 and 1000.")) - d.placeholder = "500" - d.rmempty = true - d.datatype="uinteger" - d.default = container_info.HostConfig.BlkioWeight - - m.handle = function(self, state, data) - if state == FORM_VALID then - local memory = data.memory - if memory and memory ~= 0 then - _,_,n,unit = memory:find("([%d%.]+)([%l%u]+)") - if n then - unit = unit and unit:sub(1,1):upper() or "B" - if unit == "M" then - memory = tonumber(n) * 1024 * 1024 - elseif unit == "G" then - memory = tonumber(n) * 1024 * 1024 * 1024 - elseif unit == "K" then - memory = tonumber(n) * 1024 - else - memory = tonumber(n) - end - end - end - request_body = { - BlkioWeight = tonumber(data.blkioweight), - NanoCPUs = tonumber(data.cpus)*10^9, - Memory = tonumber(memory), - CpuShares = tonumber(data.cpushares) - } - docker:clear_status() - docker:append_status("Containers: update " .. container_id .. "...") - local res = dk.containers:update({id = container_id, body = request_body}) - if res and res.code >= 300 then - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) - else - docker:clear_status() - end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/container/"..container_id.."/edit")) - end - end -elseif action == "file" then - local filesection= m:section(SimpleSection) - m.submit = false - m.reset = false - filesection.template = "dockerman/container_file" - filesection.container = container_id -elseif action == "logs" then - local logsection= m:section(SimpleSection) - local logs = "" - local query ={ - stdout = 1, - stderr = 1, - tail = 1000 - } - local logs = dk.containers:logs({id = container_id, query = query}) - if logs.code == 200 then - logsection.syslog=logs.body - else - logsection.syslog="Get Logs ERROR\n"..logs.code..": "..logs.body - end - logsection.title=translate("Container Logs") - logsection.template = "dockerman/logs" - m.submit = false - m.reset = false -elseif action == "stats" then - local response = dk.containers:top({id = container_id, query = {ps_args="-aux"}}) - local container_top - if response.code == 200 then - container_top=response.body - else - response = dk.containers:top({id = container_id}) - if response.code == 200 then - container_top=response.body - end - end - - if type(container_top) == "table" then - container_top=response.body - stat_section = m:section(SimpleSection) - stat_section.container_id = container_id - stat_section.template = "dockerman/stats" - table_stats = {cpu={key=translate("CPU Useage"),value='-'},memory={key=translate("Memory Useage"),value='-'}} - stat_section = m:section(Table, table_stats, translate("Stats")) - stat_section:option(DummyValue, "key", translate("Stats")).width="33%" - - stat_section:option(DummyValue, "value") - top_section= m:section(Table, container_top.Processes, translate("TOP")) - for i, v in ipairs(container_top.Titles) do - top_section:option(DummyValue, i, translate(v)) - end -end -m.submit = false -m.reset = false -end - - -return m diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua deleted file mode 100644 index 8c95ed77d..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua +++ /dev/null @@ -1,197 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -local http = require "luci.http" -local uci = luci.model.uci.cursor() -local docker = require "luci.model.docker" -local dk = docker.new() - -local images, networks, containers -local res = dk.images:list() -if res.code <300 then images = res.body else return end -res = dk.networks:list() -if res.code <300 then networks = res.body else return end -res = dk.containers:list({query = {all=true}}) -if res.code <300 then containers = res.body else return end - -local urlencode = luci.http.protocol and luci.http.protocol.urlencode or luci.util.urlencode - -function get_containers() - local data = {} - if type(containers) ~= "table" then return nil end - for i, v in ipairs(containers) do - local index = v.Created .. v.Id - data[index]={} - data[index]["_selected"] = 0 - data[index]["_id"] = v.Id:sub(1,12) - data[index]["_name"] = v.Names[1]:sub(2) - data[index]["_status"] = v.Status - if v.Status:find("^Up") then - data[index]["_status"] = ''.. data[index]["_status"] .. "" - else - data[index]["_status"] = ''.. data[index]["_status"] .. "" - end - if (type(v.NetworkSettings) == "table" and type(v.NetworkSettings.Networks) == "table") then - for networkname, netconfig in pairs(v.NetworkSettings.Networks) do - data[index]["_network"] = (data[index]["_network"] ~= nil and (data[index]["_network"] .." | ") or "").. networkname .. (netconfig.IPAddress ~= "" and (": " .. netconfig.IPAddress) or "") - end - end - -- networkmode = v.HostConfig.NetworkMode ~= "default" and v.HostConfig.NetworkMode or "bridge" - -- data[index]["_network"] = v.NetworkSettings.Networks[networkmode].IPAddress or nil - -- local _, _, image = v.Image:find("^sha256:(.+)") - -- if image ~= nil then - -- image=image:sub(1,12) - -- end - - if v.Ports then - data[index]["_ports"] = nil - for _,v2 in ipairs(v.Ports) do - data[index]["_ports"] = (data[index]["_ports"] and (data[index]["_ports"] .. ", ") or "") .. (v2.PublicPort and (v2.PublicPort .. ":") or "") .. (v2.PrivatePort and (v2.PrivatePort .."/") or "") .. (v2.Type and v2.Type or "") - end - end - for ii,iv in ipairs(images) do - if iv.Id == v.ImageID then - data[index]["_image"] = iv.RepoTags and iv.RepoTags[1] or (iv.RepoDigests[1]:gsub("(.-)@.+", "%1") .. ":none") - end - end - - data[index]["_image_id"] = v.ImageID:sub(8,20) - data[index]["_command"] = v.Command - end - return data -end - -local c_lists = get_containers() --- list Containers --- m = Map("docker", translate("Docker")) -m = SimpleForm("docker", translate("Docker")) -m.template = "dockerman/cbi/xsimpleform" -m.submit=false -m.reset=false - -docker_status = m:section(SimpleSection) -docker_status.template = "dockerman/apply_widget" -docker_status.err=nixio.fs.readfile(dk.options.status_path) --- luci.util.perror(docker_status.err) -if docker_status.err then docker:clear_status() end - -c_table = m:section(Table, c_lists, translate("Containers")) -c_table.nodescr=true --- v.template = "cbi/tblsection" --- v.sortable = true -container_selecter = c_table:option(Flag, "_selected","") -container_selecter.disabled = 0 -container_selecter.enabled = 1 -container_selecter.default = 0 - -container_id = c_table:option(DummyValue, "_id", translate("ID")) -container_id.width="10%" -container_name = c_table:option(DummyValue, "_name", translate("Container Name")) -container_name.width="20%" -container_name.template = "dockerman/cbi/dummyvalue" -container_name.href = function (self, section) - return luci.dispatcher.build_url("admin/services/docker/container/" .. urlencode(container_id:cfgvalue(section))) -end -container_status = c_table:option(DummyValue, "_status", translate("Status")) -container_status.width="15%" -container_status.rawhtml=true -container_ip = c_table:option(DummyValue, "_network", translate("Network")) -container_ip.width="15%" -container_ports = c_table:option(DummyValue, "_ports", translate("Ports")) -container_ports.width="10%" -container_image = c_table:option(DummyValue, "_image", translate("Image")) -container_image.template = "dockerman/cbi/dummyvalue" -container_image.width="10%" --- container_image.href = function (self, section) --- return luci.dispatcher.build_url("admin/services/docker/image/" .. urlencode(c_lists[section]._image_id)) --- end -container_command = c_table:option(DummyValue, "_command", translate("Command")) -container_command.width="20%" - -container_selecter.write=function(self, section, value) - c_lists[section]._selected = value -end - -local start_stop_remove = function(m,cmd) - -- luci.template.render("admin_uci/apply", { - -- changes = next(changes) and changes, - -- configs = reload - -- }) - - local c_selected = {} - -- 遍历table中sectionid - local c_table_sids = c_table:cfgsections() - for _, c_table_sid in ipairs(c_table_sids) do - -- 得到选中项的名字 - if c_lists[c_table_sid]._selected == 1 then - c_selected[#c_selected+1] = container_name:cfgvalue(c_table_sid) - end - end - if #c_selected >0 then - docker:clear_status() - local success = true - for _,cont in ipairs(c_selected) do - docker:append_status("Containers: " .. cmd .. " " .. cont .. "...") - local res = dk.containers[cmd](dk, {id = cont}) - if res and res.code >= 300 then - success = false - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "
") - else - docker:append_status("done
") - end - end - if success then docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/containers")) - end -end - -action_section = m:section(Table,{{}}) -action_section.notitle=true -action_section.rowcolors=false -action_section.template="cbi/nullsection" - -btnnew=action_section:option(Button, "_new") -btnnew.inputtitle= translate("New") -btnnew.template = "dockerman/cbi/inlinebutton" -btnnew.inputstyle = "add" -btnnew.forcewrite = true -btnstart=action_section:option(Button, "_start") -btnstart.template = "dockerman/cbi/inlinebutton" -btnstart.inputtitle=translate("Start") -btnstart.inputstyle = "apply" -btnstart.forcewrite = true -btnrestart=action_section:option(Button, "_restart") -btnrestart.template = "dockerman/cbi/inlinebutton" -btnrestart.inputtitle=translate("Restart") -btnrestart.inputstyle = "reload" -btnrestart.forcewrite = true -btnstop=action_section:option(Button, "_stop") -btnstop.template = "dockerman/cbi/inlinebutton" -btnstop.inputtitle=translate("Stop") -btnstop.inputstyle = "reset" -btnstop.forcewrite = true -btnremove=action_section:option(Button, "_remove") -btnremove.template = "dockerman/cbi/inlinebutton" -btnremove.inputtitle=translate("Remove") -btnremove.inputstyle = "remove" -btnremove.forcewrite = true -btnnew.write = function(self, section) - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newcontainer")) -end -btnstart.write = function(self, section) - start_stop_remove(m,"start") -end -btnrestart.write = function(self, section) - start_stop_remove(m,"restart") -end -btnremove.write = function(self, section) - start_stop_remove(m,"remove") -end -btnstop.write = function(self, section) - start_stop_remove(m,"stop") -end - -return m diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua deleted file mode 100644 index 1f8902eab..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua +++ /dev/null @@ -1,176 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -local uci = luci.model.uci.cursor() -local docker = require "luci.model.docker" -local dk = docker.new() - -local containers, images -local res = dk.images:list() -if res.code <300 then images = res.body else return end -res = dk.containers:list({query = {all=true}}) -if res.code <300 then containers = res.body else return end - -function get_images() - local data = {} - for i, v in ipairs(images) do - local index = v.Created .. v.Id - data[index]={} - data[index]["_selected"] = 0 - data[index]["_id"] = v.Id:sub(8,20) - if v.RepoTags then - for i, v1 in ipairs(v.RepoTags) do - data[index]["_tags"] =(data[index]["_tags"] and ( data[index]["_tags"] .. "" )or "") .. v1 - end - else - _,_, data[index]["_tags"] = v.RepoDigests[1]:find("^(.-)@.+") - data[index]["_tags"]=data[index]["_tags"]..":none" - end - for ci,cv in ipairs(containers) do - if v.Id == cv.ImageID then - data[index]["_containers"] = (data[index]["_containers"] and (data[index]["_containers"] .. " | ") or "").. - "".. cv.Names[1]:sub(2).."" - end - end - data[index]["_size"] = string.format("%.2f", tostring(v.Size/1024/1024)).."MB" - data[index]["_created"] = os.date("%Y/%m/%d %H:%M:%S",v.Created) - end - return data -end - -local image_list = get_images() - --- m = Map("docker", translate("Docker")) -m = SimpleForm("docker", translate("Docker")) -m.template = "dockerman/cbi/xsimpleform" -m.submit=false -m.reset=false - -local pull_value={{_image_tag_name="", _registry="index.docker.io"}} -local pull_section = m:section(Table,pull_value, translate("Pull Image")) -pull_section.template="cbi/nullsection" -local tag_name = pull_section:option(Value, "_image_tag_name") -tag_name.template = "dockerman/cbi/inlinevalue" -tag_name.placeholder="hello-world:latest" -local registry = pull_section:option(Value, "_registry") -registry.template = "dockerman/cbi/inlinevalue" -registry:value("index.docker.io", "Docker Hub") -registry:value("hub-mirror.c.163.com", "163 Mirror") -registry:value("mirror.ccs.tencentyun.com", "Tencent Mirror") -registry:value("docker.mirrors.ustc.edu.cn", "USTC Mirror") -local action_pull = pull_section:option(Button, "_pull") -action_pull.inputtitle= translate("Pull") -action_pull.template = "dockerman/cbi/inlinebutton" -action_pull.inputstyle = "add" -tag_name.write = function(self, section,value) - local hastag = value:find(":") - if not hastag then - value = value .. ":latest" - end - pull_value[section]["_image_tag_name"] = value -end -registry.write = function(self, section,value) - pull_value[section]["_registry"] = value -end -action_pull.write = function(self, section) - local tag = pull_value[section]["_image_tag_name"] - local server = pull_value[section]["_registry"] - --去掉协议前缀和后缀 - local _,_,tmp = server:find(".-://([%.%w%-%_]+)") - if not tmp then - _,_,server = server:find("([%.%w%-%_]+)") - end - local json_stringify = luci.jsonc and luci.jsonc.stringify - if tag and tag ~= "" then - docker:clear_status() - docker:append_status("Images: " .. "pulling" .. " " .. tag .. "...") - local x_auth = nixio.bin.b64encode(json_stringify({serveraddress= server})) - local res = dk.images:create({query = {fromImage=tag}, header={["X-Registry-Auth"] = x_auth}}) - if res and res.code >=300 then - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "
") - else - docker:append_status("done
") - end - else - docker:append_status("fail code: 400 please input the name of image name!") - end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/images")) -end - -image_table = m:section(Table, image_list, translate("Images")) - -image_selecter = image_table:option(Flag, "_selected","") -image_selecter.disabled = 0 -image_selecter.enabled = 1 -image_selecter.default = 0 - -image_id = image_table:option(DummyValue, "_id", translate("ID")) -image_table:option(DummyValue, "_tags", translate("RepoTags")).rawhtml = true -image_table:option(DummyValue, "_containers", translate("Containers")).rawhtml = true -image_table:option(DummyValue, "_size", translate("Size")) -image_table:option(DummyValue, "_created", translate("Created")) -image_selecter.write = function(self, section, value) - image_list[section]._selected = value -end - -local remove_action = function(force) - local image_selected = {} - -- 遍历table中sectionid - local image_table_sids = image_table:cfgsections() - for _, image_table_sid in ipairs(image_table_sids) do - -- 得到选中项的名字 - if image_list[image_table_sid]._selected == 1 then - image_selected[#image_selected+1] = image_id:cfgvalue(image_table_sid) - end - end - if next(image_selected) ~= nil then - local success = true - docker:clear_status() - for _,img in ipairs(image_selected) do - docker:append_status("Images: " .. "remove" .. " " .. img .. "...") - local query - if force then query = {force = true} end - local msg = dk.images:remove({id = img, query = query}) - if msg.code ~= 200 then - docker:append_status("fail code:" .. msg.code.." ".. (msg.body.message and msg.body.message or msg.message).. "
") - success = false - else - docker:append_status("done
") - end - end - if success then docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/images")) - end -end - -docker_status = m:section(SimpleSection) -docker_status.template = "dockerman/apply_widget" -docker_status.err=nixio.fs.readfile(dk.options.status_path) -if docker_status.err then docker:clear_status() end - -action = m:section(Table,{{}}) -action.notitle=true -action.rowcolors=false -action.template="cbi/nullsection" - -btnremove = action:option(Button, "remove") -btnremove.inputtitle= translate("Remove") -btnremove.template = "dockerman/cbi/inlinebutton" -btnremove.inputstyle = "remove" -btnremove.forcewrite = true -btnremove.write = function(self, section) - remove_action() -end - -btnforceremove = action:option(Button, "forceremove") -btnforceremove.inputtitle= translate("Force Remove") -btnforceremove.template = "dockerman/cbi/inlinebutton" -btnforceremove.inputstyle = "remove" -btnforceremove.forcewrite = true -btnforceremove.write = function(self, section) - remove_action(true) -end -return m diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua deleted file mode 100644 index ae8ed0bac..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua +++ /dev/null @@ -1,123 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -local uci = luci.model.uci.cursor() -local docker = require "luci.model.docker" -local dk = docker.new() -local networks -local res = dk.networks:list() -if res.code < 300 then networks = res.body else return end - -local get_networks = function () - local data = {} - - if type(networks) ~= "table" then return nil end - for i, v in ipairs(networks) do - local index = v.Created .. v.Id - data[index]={} - data[index]["_selected"] = 0 - data[index]["_id"] = v.Id:sub(1,12) - data[index]["_name"] = v.Name - data[index]["_driver"] = v.Driver - if v.Driver == "bridge" then - data[index]["_interface"] = v.Options["com.docker.network.bridge.name"] - elseif v.Driver == "macvlan" then - data[index]["_interface"] = v.Options.parent - end - data[index]["_subnet"] = v.IPAM and v.IPAM.Config[1] and v.IPAM.Config[1].Subnet or nil - data[index]["_gateway"] = v.IPAM and v.IPAM.Config[1] and v.IPAM.Config[1].Gateway or nil - end - return data -end - -local network_list = get_networks() --- m = Map("docker", translate("Docker")) -m = SimpleForm("docker", translate("Docker")) -m.template = "dockerman/cbi/xsimpleform" -m.submit=false -m.reset=false - -network_table = m:section(Table, network_list, translate("Networks")) -network_table.nodescr=true - -network_selecter = network_table:option(Flag, "_selected","") -network_selecter.template = "dockerman/cbi/xfvalue" -network_id = network_table:option(DummyValue, "_id", translate("ID")) -network_selecter.disabled = 0 -network_selecter.enabled = 1 -network_selecter.default = 0 -network_selecter.render = function(self, section, scope) - self.disable = 0 - if network_list[section]["_name"] == "bridge" or network_list[section]["_name"] == "none" or network_list[section]["_name"] == "host" then - self.disable = 1 - end - Flag.render(self, section, scope) -end - -network_name = network_table:option(DummyValue, "_name", translate("Network Name")) -network_driver = network_table:option(DummyValue, "_driver", translate("Driver")) -network_interface = network_table:option(DummyValue, "_interface", translate("Parent Interface")) -network_subnet = network_table:option(DummyValue, "_subnet", translate("Subnet")) -network_gateway = network_table:option(DummyValue, "_gateway", translate("Gateway")) - -network_selecter.write = function(self, section, value) - network_list[section]._selected = value -end - -docker_status = m:section(SimpleSection) -docker_status.template = "dockerman/apply_widget" -docker_status.err=nixio.fs.readfile(dk.options.status_path) -if docker_status.err then docker:clear_status() end - -action = m:section(Table,{{}}) -action.notitle=true -action.rowcolors=false -action.template="cbi/nullsection" -btnnew=action:option(Button, "_new") -btnnew.inputtitle= translate("New") -btnnew.template = "dockerman/cbi/inlinebutton" -btnnew.notitle=true -btnnew.inputstyle = "add" -btnnew.forcewrite = true -btnnew.write = function(self, section) - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newnetwork")) -end -btnremove = action:option(Button, "_remove") -btnremove.inputtitle= translate("Remove") -btnremove.template = "dockerman/cbi/inlinebutton" -btnremove.inputstyle = "remove" -btnremove.forcewrite = true -btnremove.write = function(self, section) - local network_selected = {} - -- 遍历table中sectionid - local network_table_sids = network_table:cfgsections() - for _, network_table_sid in ipairs(network_table_sids) do - -- 得到选中项的名字 - if network_list[network_table_sid]._selected == 1 then - network_selected[#network_selected+1] = network_name:cfgvalue(network_table_sid) - end - end - if next(network_selected) ~= nil then - local success = true - docker:clear_status() - for _,net in ipairs(network_selected) do - docker:append_status("Networks: " .. "remove" .. " " .. net .. "...") - local res = dk.networks["remove"](dk, {id = net}) - if res and res.code >= 300 then - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "
") - success = false - else - docker:append_status("done
") - end - end - if success then - docker:clear_status() - end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/networks")) - end -end - -return m diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua deleted file mode 100644 index f92a1aaae..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua +++ /dev/null @@ -1,579 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -require "math" -local uci = luci.model.uci.cursor() -local docker = require "luci.model.docker" -local dk = docker.new() -local cmd_line = table.concat(arg, '/') -local create_body = {} - -local images = dk.images:list().body -local networks = dk.networks:list().body -local containers = dk.containers:list({query = {all=true}}).body - -local is_quot_complete = function(str) - if not str then return true end - local num = 0, w - for w in str:gmatch("[\"\']") do - num = num + 1 - end - if math.fmod(num, 2) ~= 0 then - return false - else - return true - end -end - --- reslvo default config -local default_config = { } -if cmd_line and cmd_line:match("^docker.+") then - local key = nil, _key - --cursor = 0: docker run - --cursor = 1: resloving para - --cursor = 2: resloving image - --cursor > 2: resloving command - local cursor = 0 - for w in cmd_line:gmatch("[^%s]+") do - -- skip '\' - if w == '\\' then - elseif _key then - -- there is a value that unpair quotation marks: - -- "i was a ok man" - -- now we only get: "i - if _key == "mount" or _key == "link" or _key == "env" or _key == "dns" or _key == "port" or _key == "device" or _key == "tmpfs" then - default_config[_key][#default_config[_key]] = default_config[_key][#default_config[_key]] .. " " .. w - if is_quot_complete(default_config[_key][#default_config[_key]]) then - -- clear quotation marks - default_config[_key][#default_config[_key]] = default_config[_key][#default_config[_key]]:gsub("[\"\']", "") - _key = nil - end - else - default_config[_key] = default_config[_key] .. " ".. w - if is_quot_complete(default_config[_key]) then - -- clear quotation marks - default_config[_key] = default_config[_key]:gsub("[\"\']", "") - _key = nil - end - end - -- start with '-' - elseif w:match("^%-+.+") and cursor <= 1 then - --key=value - local val - key, val = w:match("^%-+(.-)=(.+)") - -- -dit - if not key then key = w:match("^%-+(.+)") end - - if not key then - key = w:match("^%-(.+)") - if key:match("i") or key:match("t") or key:match("d") then - if key:match("i") then default_config["interactive"] = true end - if key:match("t") then default_config["tty"] = true end - -- clear key - key = nil - end - end - - if key == "v" or key == "volume" then - key = "mount" - elseif key == "p" or key == "publish" then - key = "port" - elseif key == "e" then - key = "env" - elseif key == "dns" then - key = "dns" - elseif key == "net" then - key = "network" - elseif key == "h" or key == "hostname" then - key = "hostname" - elseif key == "cpu-shares" then - key = "cpushares" - elseif key == "m" then - key = "memory" - elseif key == "blkio-weight" then - key = "blkioweight" - elseif key == "privileged" then - default_config["privileged"] = true - key = nil - elseif key == "cap-add" then - default_config["privileged"] = true - end - --key=value - if val then - if key == "mount" or key == "link" or key == "env" or key == "dns" or key == "port" or key == "device" or key == "tmpfs" then - if not default_config[key] then default_config[key] = {} end - table.insert( default_config[key], val ) - -- clear quotation marks - default_config[key][#default_config[key]] = default_config[key][#default_config[key]]:gsub("[\"\']", "") - else - default_config[key] = val - -- clear quotation marks - default_config[key] = default_config[key]:gsub("[\"\']", "") - end - -- if there are " or ' in val and separate by space, we need keep the _key to link with next w - if is_quot_complete(val) then - _key = nil - else - _key = key - end - -- clear key - key = nil - end - cursor = 1 - -- value - elseif key and type(key) == "string" and cursor == 1 then - if key == "mount" or key == "link" or key == "env" or key == "dns" or key == "port" or key == "device" or key == "tmpfs" then - if not default_config[key] then default_config[key] = {} end - table.insert( default_config[key], w ) - -- clear quotation marks - default_config[key][#default_config[key]] = default_config[key][#default_config[key]]:gsub("[\"\']", "") - else - default_config[key] = w - -- clear quotation marks - default_config[key] = default_config[key]:gsub("[\"\']", "") - end - if key == "cpus" or key == "cpushare" or key == "memory" or key == "blkioweight" or key == "device" or key == "tmpfs" then - default_config["advance"] = 1 - end - -- if there are " or ' in val and separate by space, we need keep the _key to link with next w - if is_quot_complete(w) then - _key = nil - else - _key = key - end - key = nil - cursor = 1 - --image and command - elseif cursor >= 1 and key == nil then - if cursor == 1 then - default_config["image"] = w - elseif cursor > 1 then - default_config["command"] = (default_config["command"] and (default_config["command"] .. " " )or "") .. w - end - cursor = cursor + 1 - end - end -elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then - local container_id = cmd_line:match("^duplicate/(.+)") - create_body = dk:containers_duplicate_config({id = container_id}) - if not create_body.HostConfig then create_body.HostConfig = {} end - if next(create_body) ~= nil then - default_config.name = nil - default_config.image = create_body.Image - default_config.hostname = create_body.Hostname - default_config.tty = create_body.Tty and true or false - default_config.interactive = create_body.OpenStdin and true or false - default_config.privileged = create_body.HostConfig.Privileged and true or false - default_config.restart = create_body.HostConfig.RestartPolicy and create_body.HostConfig.RestartPolicy.name or nil - -- default_config.network = create_body.HostConfig.NetworkMode == "default" and "bridge" or create_body.HostConfig.NetworkMode - -- if container has leave original network, and add new network, .HostConfig.NetworkMode is INcorrect, so using first child of .NetworkingConfig.EndpointsConfig - default_config.network = next(create_body.NetworkingConfig.EndpointsConfig) - default_config.ip = default_config.network and default_config.network ~= "bridge" and default_config.network ~= "host" and default_config.network ~= "null" and create_body.NetworkingConfig.EndpointsConfig[default_config.network].IPAMConfig and create_body.NetworkingConfig.EndpointsConfig[default_config.network].IPAMConfig.IPv4Address or nil - default_config.link = create_body.HostConfig.Links - default_config.env = create_body.Env - default_config.dns = create_body.HostConfig.Dns - default_config.mount = create_body.HostConfig.Binds - - if create_body.HostConfig.PortBindings and type(create_body.HostConfig.PortBindings) == "table" then - default_config.port = {} - for k, v in pairs(create_body.HostConfig.PortBindings) do - table.insert( default_config.port, v[1].HostPort..":"..k:match("^(%d+)/.+").."/"..k:match("^%d+/(.+)") ) - end - end - - default_config.user = create_body.User or nil - default_config.command = create_body.Cmd and type(create_body.Cmd) == "table" and table.concat(create_body.Cmd, " ") or nil - default_config.advance = 1 - default_config.cpus = create_body.HostConfig.NanoCPUs - default_config.cpushares = create_body.HostConfig.CpuShares - default_config.memory = create_body.HostConfig.Memory - default_config.blkioweight = create_body.HostConfig.BlkioWeight - - if create_body.HostConfig.Devices and type(create_body.HostConfig.Devices) == "table" then - default_config.device = {} - for _, v in ipairs(create_body.HostConfig.Devices) do - table.insert( default_config.device, v.PathOnHost..":"..v.PathInContainer..(v.CgroupPermissions ~= "" and (":" .. v.CgroupPermissions) or "") ) - end - end - - default_config.tmpfs = create_body.HostConfig.Tmpfs - end -end - -local m = SimpleForm("docker", translate("Docker")) -m.template = "dockerman/cbi/xsimpleform" -m.redirect = luci.dispatcher.build_url("admin", "services","docker", "containers") --- m.reset = false --- m.submit = false --- new Container - -docker_status = m:section(SimpleSection) -docker_status.template = "dockerman/apply_widget" -docker_status.err=nixio.fs.readfile(dk.options.status_path) -if docker_status.err then docker:clear_status() end - -local s = m:section(SimpleSection, translate("New Container")) -s.addremove = true -s.anonymous = true - -local d = s:option(DummyValue,"cmd_line", translate("Resolv CLI")) -d.rawhtml = true -d.template = "dockerman/resolv_container" - -d = s:option(Value, "name", translate("Container Name")) -d.rmempty = true -d.default = default_config.name or nil - -d = s:option(Flag, "interactive", translate("Interactive (-i)")) -d.rmempty = true -d.disabled = 0 -d.enabled = 1 -d.default = default_config.interactive and 1 or 0 - -d = s:option(Flag, "tty", translate("TTY (-t)")) -d.rmempty = true -d.disabled = 0 -d.enabled = 1 -d.default = default_config.tty and 1 or 0 - -d = s:option(Value, "image", translate("Docker Image")) -d.rmempty = true -d.default = default_config.image or nil -for _, v in ipairs (images) do - if v.RepoTags then - d:value(v.RepoTags[1], v.RepoTags[1]) - end -end - -d = s:option(Flag, "_force_pull", translate("Always pull image first")) -d.rmempty = true -d.disabled = 0 -d.enabled = 1 -d.default = 0 - -d = s:option(Flag, "privileged", translate("Privileged")) -d.rmempty = true -d.disabled = 0 -d.enabled = 1 -d.default = default_config.privileged and 1 or 0 - -d = s:option(ListValue, "restart", translate("Restart Policy")) -d.rmempty = true - -d:value("no", "No") -d:value("unless-stopped", "Unless stopped") -d:value("always", "Always") -d:value("on-failure", "On failure") -d.default = default_config.restart or "unless-stopped" - -local d_network = s:option(ListValue, "network", translate("Networks")) -d_network.rmempty = true -d_network.default = default_config.network or "bridge" - -local d_ip = s:option(Value, "ip", translate("IPv4 Address")) -d_ip.datatype="ip4addr" -d_ip:depends("network", "nil") -d_ip.default = default_config.ip or nil - -d = s:option(DynamicList, "link", translate("Links with other containers")) -d.template = "dockerman/cbi/xdynlist" -d.placeholder = "container_name:alias" -d.rmempty = true -d:depends("network", "bridge") -d.default = default_config.link or nil - -d = s:option(DynamicList, "dns", translate("Set custom DNS servers")) -d.template = "dockerman/cbi/xdynlist" -d.placeholder = "8.8.8.8" -d.rmempty = true -d.default = default_config.dns or nil - -d = s:option(Value, "user", translate("User(-u)"), translate("The user that commands are run as inside the container.(format: name|uid[:group|gid])")) -d.placeholder = "1000:1000" -d.rmempty = true -d.default = default_config.user or nil - -d = s:option(DynamicList, "env", translate("Environmental Variable(-e)"), translate("Set environment variables to inside the container")) -d.template = "dockerman/cbi/xdynlist" -d.placeholder = "TZ=Asia/Shanghai" -d.rmempty = true -d.default = default_config.env or nil - -d = s:option(DynamicList, "mount", translate("Bind Mount(-v)"), translate("Bind mount a volume")) -d.template = "dockerman/cbi/xdynlist" -d.placeholder = "/media:/media:slave" -d.rmempty = true -d.default = default_config.mount or nil - -local d_ports = s:option(DynamicList, "port", translate("Exposed Ports(-p)"), translate("Publish container's port(s) to the host")) -d_ports.template = "dockerman/cbi/xdynlist" -d_ports.placeholder = "2200:22/tcp" -d_ports.rmempty = true -d_ports.default = default_config.port or nil - -d = s:option(Value, "command", translate("Run command")) -d.placeholder = "/bin/sh init.sh" -d.rmempty = true -d.default = default_config.command or nil - -d = s:option(Flag, "advance", translate("Advance")) -d.rmempty = true -d.disabled = 0 -d.enabled = 1 -d.default = default_config.advance or 0 - -d = s:option(Value, "hostname", translate("Host Name"), translate("The hostname to use for the container")) -d.rmempty = true -d.default = default_config.hostname or nil -d:depends("advance", 1) - -d = s:option(DynamicList, "device", translate("Device(--device)"), translate("Add host device to the container")) -d.template = "dockerman/cbi/xdynlist" -d.placeholder = "/dev/sda:/dev/xvdc:rwm" -d.rmempty = true -d:depends("advance", 1) -d.default = default_config.device or nil - -d = s:option(DynamicList, "tmpfs", translate("Tmpfs(--tmpfs)"), translate("Mount tmpfs directory")) -d.template = "dockerman/cbi/xdynlist" -d.placeholder = "/run:rw,noexec,nosuid,size=65536k" -d.rmempty = true -d:depends("advance", 1) -d.default = default_config.tmpfs or nil - -d = s:option(Value, "cpus", translate("CPUs"), translate("Number of CPUs. Number is a fractional number. 0.000 means no limit.")) -d.placeholder = "1.5" -d.rmempty = true -d:depends("advance", 1) -d.datatype="ufloat" -d.default = default_config.cpus or nil - -d = s:option(Value, "cpushares", translate("CPU Shares Weight"), translate("CPU shares relative weight, if 0 is set, the system will ignore the value and use the default of 1024.")) -d.placeholder = "1024" -d.rmempty = true -d:depends("advance", 1) -d.datatype="uinteger" -d.default = default_config.cpushares or nil - -d = s:option(Value, "memory", translate("Memory"), translate("Memory limit (format: []). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M.")) -d.placeholder = "128m" -d.rmempty = true -d:depends("advance", 1) -d.default = default_config.memory or nil - -d = s:option(Value, "blkioweight", translate("Block IO Weight"), translate("Block IO weight (relative weight) accepts a weight value between 10 and 1000.")) -d.placeholder = "500" -d.rmempty = true -d:depends("advance", 1) -d.datatype="uinteger" -d.default = default_config.blkioweight or nil - - -for _, v in ipairs (networks) do - if v.Name then - local parent = v.Options and v.Options.parent or nil - local ip = v.IPAM and v.IPAM.Config and v.IPAM.Config[1] and v.IPAM.Config[1].Subnet or nil - ipv6 = v.IPAM and v.IPAM.Config and v.IPAM.Config[2] and v.IPAM.Config[2].Subnet or nil - local network_name = v.Name .. " | " .. v.Driver .. (parent and (" | " .. parent) or "") .. (ip and (" | " .. ip) or "").. (ipv6 and (" | " .. ipv6) or "") - d_network:value(v.Name, network_name) - - if v.Name ~= "none" and v.Name ~= "bridge" and v.Name ~= "host" then - d_ip:depends("network", v.Name) - end - - if v.Driver == "bridge" then - d_ports:depends("network", v.Name) - end - end -end - -m.handle = function(self, state, data) - if state ~= FORM_VALID then return end - local tmp - local name = data.name or ("luci_" .. os.date("%Y%m%d%H%M%S")) - local hostname = data.hostname - local tty = type(data.tty) == "number" and (data.tty == 1 and true or false) or default_config.tty or false - local interactive = type(data.interactive) == "number" and (data.interactive == 1 and true or false) or default_config.interactive or false - local image = data.image - local user = data.user - if image and not image:match(".-:.+") then - image = image .. ":latest" - end - local privileged = type(data.privileged) == "number" and (data.privileged == 1 and true or false) or default_config.privileged or false - local restart = data.restart - local env = data.env - local dns = data.dns - local network = data.network - local ip = (network ~= "bridge" and network ~= "host" and network ~= "none") and data.ip or nil - local mount = data.mount - local memory = data.memory or 0 - local cpushares = data.cpushares or 0 - local cpus = data.cpus or 0 - local blkioweight = data.blkioweight or 500 - - local portbindings = {} - local exposedports = {} - local tmpfs = {} - tmp = data.tmpfs - if type(tmp) == "table" then - for i, v in ipairs(tmp)do - local _,_, k,v1 = v:find("(.-):(.+)") - if k and v1 then - tmpfs[k]=v1 - end - end - end - - local device = {} - tmp = data.device - if type(tmp) == "table" then - for i, v in ipairs(tmp) do - local t = {} - local _,_, h, c, p = v:find("(.-):(.-):(.+)") - if h and c then - t['PathOnHost'] = h - t['PathInContainer'] = c - t['CgroupPermissions'] = p or "rwm" - else - local _,_, h, c = v:find("(.-):(.+)") - if h and c then - t['PathOnHost'] = h - t['PathInContainer'] = c - t['CgroupPermissions'] = "rwm" - end - end - if next(t) ~= nil then - table.insert( device, t ) - end - end - end - - tmp = data.port or {} - for i, v in ipairs(tmp) do - for v1 ,v2 in string.gmatch(v, "(%d+):([^%s]+)") do - local _,_,p= v2:find("^%d+/(%w+)") - if p == nil then - v2=v2..'/tcp' - end - portbindings[v2] = {{HostPort=v1}} - exposedports[v2] = {HostPort=v1} - end - end - - local link = data.link - tmp = data.command - local command = {} - if tmp ~= nil then - for v in string.gmatch(tmp, "[^%s]+") do - command[#command+1] = v - end - end - if memory ~= 0 then - _,_,n,unit = memory:find("([%d%.]+)([%l%u]+)") - if n then - unit = unit and unit:sub(1,1):upper() or "B" - if unit == "M" then - memory = tonumber(n) * 1024 * 1024 - elseif unit == "G" then - memory = tonumber(n) * 1024 * 1024 * 1024 - elseif unit == "K" then - memory = tonumber(n) * 1024 - else - memory = tonumber(n) - end - end - end - - create_body.Hostname = network ~= "host" and (hostname or name) or nil - create_body.Tty = tty and true or false - create_body.OpenStdin = interactive and true or false - create_body.User = user - create_body.Cmd = (#command ~= 0) and command or nil - create_body.Env = env - create_body.Image = image - create_body.ExposedPorts = (next(exposedports) ~= nil) and exposedports or nil - create_body.HostConfig = create_body.HostConfig or {} - create_body.HostConfig.Dns = dns - create_body.HostConfig.Binds = (#mount ~= 0) and mount or nil - create_body.HostConfig.RestartPolicy = { Name = restart, MaximumRetryCount = 0 } - create_body.HostConfig.Privileged = privileged and true or false - create_body.HostConfig.PortBindings = (next(portbindings) ~= nil) and portbindings or nil - create_body.HostConfig.Memory = tonumber(memory) - create_body.HostConfig.CpuShares = tonumber(cpushares) - create_body.HostConfig.NanoCPUs = tonumber(cpus) * 10 ^ 9 - create_body.HostConfig.BlkioWeight = tonumber(blkioweight) - if create_body.HostConfig.NetworkMode ~= network then - -- network mode changed, need to clear duplicate config - create_body.NetworkingConfig = nil - end - create_body.HostConfig.NetworkMode = network - if ip then - if create_body.NetworkingConfig and create_body.NetworkingConfig.EndpointsConfig and type(create_body.NetworkingConfig.EndpointsConfig) == "table" then - -- ip + duplicate config - for k, v in pairs (create_body.NetworkingConfig.EndpointsConfig) do - if k == network and v.IPAMConfig and v.IPAMConfig.IPv4Address then - v.IPAMConfig.IPv4Address = ip - else - create_body.NetworkingConfig.EndpointsConfig = { [network] = { IPAMConfig = { IPv4Address = ip } } } - end - break - end - else - -- ip + no duplicate config - create_body.NetworkingConfig = { EndpointsConfig = { [network] = { IPAMConfig = { IPv4Address = ip } } } } - end - elseif not create_body.NetworkingConfig then - -- no ip + no duplicate config - create_body.NetworkingConfig = nil - end - - create_body["HostConfig"]["Tmpfs"] = (next(tmpfs) ~= nil) and tmpfs or nil - create_body["HostConfig"]["Devices"] = (next(device) ~= nil) and device or nil - - if network == "bridge" and next(link) ~= nil then - create_body["HostConfig"]["Links"] = link - end - local pull_image = function(image) - local server = "index.docker.io" - local json_stringify = luci.jsonc and luci.jsonc.stringify - docker:append_status("Images: " .. "pulling" .. " " .. image .. "...") - local x_auth = nixio.bin.b64encode(json_stringify({serveraddress= server})) - local res = dk.images:create({query = {fromImage=image}, header={["X-Registry-Auth"]=x_auth}}) - if res and res.code == 200 then - docker:append_status("done
") - else - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "
") - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newcontainer")) - end - end - docker:clear_status() - local exist_image = false - if image then - for _, v in ipairs (images) do - if v.RepoTags and v.RepoTags[1] == image then - exist_image = true - break - end - end - if not exist_image then - pull_image(image) - elseif data._force_pull == 1 then - pull_image(image) - end - end - - docker:append_status("Container: " .. "create" .. " " .. name .. "...") - local res = dk.containers:create({name = name, body = create_body}) - if res and res.code == 201 then - docker:clear_status() - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/containers")) - else - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newcontainer")) - end -end - -return m diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua deleted file mode 100644 index 650667e6e..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua +++ /dev/null @@ -1,205 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -local uci = luci.model.uci.cursor() -local docker = require "luci.model.docker" -local dk = docker.new() - -m = SimpleForm("docker", translate("Docker")) -m.template = "dockerman/cbi/xsimpleform" -m.redirect = luci.dispatcher.build_url("admin", "services","docker", "networks") - -docker_status = m:section(SimpleSection) -docker_status.template = "dockerman/apply_widget" -docker_status.err=nixio.fs.readfile(dk.options.status_path) -if docker_status.err then docker:clear_status() end - -s = m:section(SimpleSection, translate("New Network")) -s.addremove = true -s.anonymous = true - -d = s:option(Value, "name", translate("Network Name")) -d.rmempty = true - -d = s:option(ListValue, "dirver", translate("Driver")) -d.rmempty = true -d:value("bridge", "bridge") -d:value("macvlan", "macvlan") -d:value("ipvlan", "ipvlan") -d:value("overlay", "overlay") - -d = s:option(Value, "parent", translate("Parent Interface")) -d.rmempty = true -d:depends("dirver", "macvlan") -d.placeholder="eth0" - -d = s:option(Value, "macvlan_mode", translate("Macvlan Mode")) -d.rmempty = true -d:depends("dirver", "macvlan") -d.default="bridge" -d:value("bridge", "bridge") -d:value("private", "private") -d:value("vepa", "vepa") -d:value("passthru", "passthru") - -d = s:option(Value, "ipvlan_mode", translate("Ipvlan Mode")) -d.rmempty = true -d:depends("dirver", "ipvlan") -d.default="l3" -d:value("l2", "l2") -d:value("l3", "l3") - -d = s:option(Flag, "ingress", translate("Ingress"), translate("Ingress network is the network which provides the routing-mesh in swarm mode.")) -d.rmempty = true -d.disabled = 0 -d.enabled = 1 -d.default = 0 -d:depends("dirver", "overlay") - -d = s:option(DynamicList, "options", translate("Options")) -d.template = "dockerman/cbi/xdynlist" -d.rmempty = true -d.placeholder="com.docker.network.driver.mtu=1500" - -d = s:option(Flag, "internal", translate("Internal"), translate("Restrict external access to the network")) -d.rmempty = true -d.disabled = 0 -d.enabled = 1 -d.default = 0 - -d = s:option(Value, "subnet", translate("Subnet")) -d.rmempty = true -d.placeholder="10.1.0.0/16" -d.datatype="ip4addr" - -d = s:option(Value, "gateway", translate("Gateway")) -d.rmempty = true -d.placeholder="10.1.1.1" -d.datatype="ip4addr" - -d = s:option(Value, "ip_range", translate("IP range")) -d.rmempty = true -d.placeholder="10.1.1.0/24" -d.datatype="ip4addr" - -d = s:option(DynamicList, "aux_address", translate("Exclude IPs")) -d.template = "dockerman/cbi/xdynlist" -d.rmempty = true -d.placeholder="my-route=10.1.1.1" - -d = s:option(Flag, "ipv6", translate("Enable IPv6")) -d.rmempty = true -d.disabled = 0 -d.enabled = 1 -d.default = 0 - -d = s:option(Value, "subnet6", translate("IPv6 Subnet")) -d.rmempty = true -d.placeholder="fe80::/10" -d.datatype="ip6addr" -d:depends("ipv6", 1) - -d = s:option(Value, "gateway6", translate("IPv6 Gateway")) -d.rmempty = true -d.placeholder="fe80::1" -d.datatype="ip6addr" -d:depends("ipv6", 1) - -m.handle = function(self, state, data) - if state == FORM_VALID then - local name = data.name - local driver = data.dirver - - local internal = data.internal == 1 and true or false - - local subnet = data.subnet - local gateway = data.gateway - local ip_range = data.ip_range - - local aux_address = {} - local tmp = data.aux_address or {} - for i,v in ipairs(tmp) do - _,_,k1,v1 = v:find("(.-)=(.+)") - aux_address[k1] = v1 - end - - local options = {} - tmp = data.options or {} - for i,v in ipairs(tmp) do - _,_,k1,v1 = v:find("(.-)=(.+)") - options[k1] = v1 - end - - local ipv6 = data.ipv6 == 1 and true or false - - local create_body={ - Name = name, - Driver = driver, - EnableIPv6 = ipv6, - IPAM = { - Driver= "default" - }, - Internal = internal - } - - if subnet or gateway or ip_range then - create_body["IPAM"]["Config"] = { - { - Subnet = subnet, - Gateway = gateway, - IPRange = ip_range, - -- AuxAddress = aux_address - -- AuxiliaryAddresses = aux_address - } - } - end - if next(aux_address)~=nil then - create_body["IPAM"]["Config"]["AuxiliaryAddresses"] = aux_address - end - if driver == "macvlan" then - create_body["Options"] = { - macvlan_mode = data.macvlan_mode, - parent = data.parent - } - elseif driver == "ipvlan" then - create_body["Options"] = { - ipvlan_mode = data.ipvlan_mode - } - elseif driver == "overlay" then - create_body["Ingress"] = data.ingerss == 1 and true or false - end - - if ipv6 and data.subnet6 and data.subnet6 then - if type(create_body["IPAM"]["Config"]) ~= "table" then - create_body["IPAM"]["Config"] = {} - end - local index = #create_body["IPAM"]["Config"] - create_body["IPAM"]["Config"][index+1] = { - Subnet = data.subnet6, - Gateway = data.gateway6 - } - end - - if next(options) ~= nil then - create_body["Options"] = create_body["Options"] or {} - for k, v in pairs(options) do - create_body["Options"][k] = v - end - end - - docker:append_status("Network: " .. "create" .. " " .. create_body.Name .. "...") - local res = dk.networks:create({body = create_body}) - if res and res.code == 201 then - docker:clear_status() - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/networks")) - else - docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "
") - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newnetwork")) - end - end -end - -return m diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua deleted file mode 100644 index da67655e4..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua +++ /dev/null @@ -1,94 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -local docker = require "luci.model.docker" -local uci = require "luci.model.uci" - -function byte_format(byte) - local suff = {"B", "KB", "MB", "GB", "TB"} - for i=1, 5 do - if byte > 1024 and i < 5 then - byte = byte / 1024 - else - return string.format("%.2f %s", byte, suff[i]) - end - end -end - -local m = Map("dockerman", translate("Docker")) -local docker_info_table = {} --- docker_info_table['0OperatingSystem'] = {_key=translate("Operating System"),_value='-'} --- docker_info_table['1Architecture'] = {_key=translate("Architecture"),_value='-'} --- docker_info_table['2KernelVersion'] = {_key=translate("Kernel Version"),_value='-'} -docker_info_table['3ServerVersion'] = {_key=translate("Docker Version"),_value='-'} -docker_info_table['4ApiVersion'] = {_key=translate("Api Version"),_value='-'} -docker_info_table['5NCPU'] = {_key=translate("CPUs"),_value='-'} -docker_info_table['6MemTotal'] = {_key=translate("Total Memory"),_value='-'} -docker_info_table['7DockerRootDir'] = {_key=translate("Docker Root Dir"),_value='-'} -docker_info_table['8IndexServerAddress'] = {_key=translate("Index Server Address"),_value='-'} - -s = m:section(Table, docker_info_table) -s:option(DummyValue, "_key", translate("Info")) -s:option(DummyValue, "_value") - -s = m:section(SimpleSection) -s.containers_running = '-' -s.images_used = '-' -s.containers_total = '-' -s.images_total = '-' -s.networks_total = '-' -s.volumes_total = '-' -local socket = luci.model.uci.cursor():get("dockerman", "local", "socket_path") -if nixio.fs.access(socket) and (require "luci.model.docker").new():_ping().code == 200 then - local dk = docker.new() - local containers_list = dk.containers:list({query = {all=true}}).body - local images_list = dk.images:list().body - local vol = dk.volumes:list() - local volumes_list = vol and vol.body and vol.body.Volumes or {} - local networks_list = dk.networks:list().body or {} - local docker_info = dk:info() - -- docker_info_table['0OperatingSystem']._value = docker_info.body.OperatingSystem - -- docker_info_table['1Architecture']._value = docker_info.body.Architecture - -- docker_info_table['2KernelVersion']._value = docker_info.body.KernelVersion - docker_info_table['3ServerVersion']._value = docker_info.body.ServerVersion - docker_info_table['4ApiVersion']._value = docker_info.headers["Api-Version"] - docker_info_table['5NCPU']._value = tostring(docker_info.body.NCPU) - docker_info_table['6MemTotal']._value = byte_format(docker_info.body.MemTotal) - docker_info_table['7DockerRootDir']._value = docker_info.body.DockerRootDir - docker_info_table['8IndexServerAddress']._value = docker_info.body.IndexServerAddress - - s.images_used = 0 - for i, v in ipairs(images_list) do - for ci,cv in ipairs(containers_list) do - if v.Id == cv.ImageID then - s.images_used = s.images_used + 1 - break - end - end - end - s.containers_running = tostring(docker_info.body.ContainersRunning) - s.images_used = tostring(s.images_used) - s.containers_total = tostring(docker_info.body.Containers) - s.images_total = tostring(#images_list) - s.networks_total = tostring(#networks_list) - s.volumes_total = tostring(#volumes_list) -end -s.template = "dockerman/overview" - - -s = m:section(NamedSection, "local", "section", translate("Setting")) - -socket_path = s:option(Value, "socket_path", translate("Socket Path")) -status_path = s:option(Value, "status_path", translate("Action Status Tempfile Path"), translate("Where you want to save the docker status file")) -wan_mode = s:option(Flag, "wan_mode", translate("Enable WAN access Dokcer"), translate("Enable WAN access docker mapped ports (need reload Docker-ce service)")) -wan_mode.enabled="true" -wan_mode.disabled="false" -debug = s:option(Flag, "debug", translate("Enable Debug"), translate("For debug, It shows all docker API actions of luci-app-dockerman in Debug Tempfile Path")) -debug.enabled="true" -debug.disabled="false" -debug_path = s:option(Value, "debug_path", translate("Debug Tempfile Path"), translate("Where you want to save the debug tempfile")) - -return m diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua deleted file mode 100644 index 9c3870732..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua +++ /dev/null @@ -1,116 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -local uci = luci.model.uci.cursor() -local docker = require "luci.model.docker" -local dk = docker.new() - -local containers, volumes -local res = dk.volumes:list() -if res.code <300 then volumes = res.body.Volumes else return end -res = dk.containers:list({query = {all=true}}) -if res.code <300 then containers = res.body else return end - -function get_volumes() - local data = {} - for i, v in ipairs(volumes) do - -- local index = v.CreatedAt .. v.Name - local index = v.Name - data[index]={} - data[index]["_selected"] = 0 - data[index]["_nameraw"] = v.Name - data[index]["_name"] = v.Name:sub(1,12) - for ci,cv in ipairs(containers) do - if cv.Mounts and type(cv.Mounts) ~= "table" then break end - for vi, vv in ipairs(cv.Mounts) do - if v.Name == vv.Name then - data[index]["_containers"] = (data[index]["_containers"] and (data[index]["_containers"] .. " | ") or "").. - "".. cv.Names[1]:sub(2).."" - end - end - end - data[index]["_driver"] = v.Driver - data[index]["_mountpoint"] = nil - for v1 in v.Mountpoint:gmatch('[^/]+') do - if v1 == index then - data[index]["_mountpoint"] = data[index]["_mountpoint"] .."/" .. v1:sub(1,12) .. "..." - else - data[index]["_mountpoint"] = (data[index]["_mountpoint"] and data[index]["_mountpoint"] or "").."/".. v1 - end - end - data[index]["_created"] = v.CreatedAt - end - return data -end - -local volume_list = get_volumes() - --- m = Map("docker", translate("Docker")) -m = SimpleForm("docker", translate("Docker")) -m.template = "dockerman/cbi/xsimpleform" -m.submit=false -m.reset=false - - -volume_table = m:section(Table, volume_list, translate("Volumes")) - -volume_selecter = volume_table:option(Flag, "_selected","") -volume_selecter.disabled = 0 -volume_selecter.enabled = 1 -volume_selecter.default = 0 - -volume_id = volume_table:option(DummyValue, "_name", translate("Name")) -volume_table:option(DummyValue, "_driver", translate("Driver")) -volume_table:option(DummyValue, "_containers", translate("Containers")).rawhtml = true -volume_table:option(DummyValue, "_mountpoint", translate("Mount Point")) -volume_table:option(DummyValue, "_created", translate("Created")) -volume_selecter.write = function(self, section, value) - volume_list[section]._selected = value -end - -docker_status = m:section(SimpleSection) -docker_status.template = "dockerman/apply_widget" -docker_status.err=nixio.fs.readfile(dk.options.status_path) -if docker_status.err then docker:clear_status() end - -action = m:section(Table,{{}}) -action.notitle=true -action.rowcolors=false -action.template="cbi/nullsection" -btnremove = action:option(Button, "remove") -btnremove.inputtitle= translate("Remove") -btnremove.template = "dockerman/cbi/inlinebutton" -btnremove.inputstyle = "remove" -btnremove.forcewrite = true -btnremove.write = function(self, section) - local volume_selected = {} - -- 遍历table中sectionid - local volume_table_sids = volume_table:cfgsections() - for _, volume_table_sid in ipairs(volume_table_sids) do - -- 得到选中项的名字 - if volume_list[volume_table_sid]._selected == 1 then - -- volume_selected[#volume_selected+1] = volume_id:cfgvalue(volume_table_sid) - volume_selected[#volume_selected+1] = volume_table_sid - end - end - if next(volume_selected) ~= nil then - local success = true - docker:clear_status() - for _,vol in ipairs(volume_selected) do - docker:append_status("Volumes: " .. "remove" .. " " .. vol .. "...") - local msg = dk.volumes["remove"](dk, {id = vol}) - if msg.code ~= 204 then - docker:append_status("fail code:" .. msg.code.." ".. (msg.body.message and msg.body.message or msg.message).. "
") - success = false - else - docker:append_status("done
") - end - end - if success then docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/volumes")) - end -end -return m diff --git a/package/lean/luci-app-dockerman/luasrc/model/docker.lua b/package/lean/luci-app-dockerman/luasrc/model/docker.lua deleted file mode 100644 index 3374752e6..000000000 --- a/package/lean/luci-app-dockerman/luasrc/model/docker.lua +++ /dev/null @@ -1,229 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface -Copyright 2019 lisaac -]]-- - -require "luci.util" -local docker = require "luci.docker" -local uci = (require "luci.model.uci").cursor() - -local _docker = {} - ---pull image and return iamge id -local update_image = function(self, image_name) - local server = "index.docker.io" - - local json_stringify = luci.jsonc and luci.jsonc.stringify - _docker:append_status("Images: " .. "pulling" .. " " .. image_name .. "...") - local x_auth = nixio.bin.b64encode(json_stringify({serveraddress= server})) - local res = self.images:create({query = {fromImage=image_name}, header={["X-Registry-Auth"]=x_auth}}) - if res and res.code < 300 then - _docker:append_status("done
") - else - _docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "
") - end - new_image_id = self.images:inspect({name = image_name}).body.Id - return new_image_id, res -end - -local table_equal = function(t1, t2) - if not t1 then return true end - if not t2 then return false end - if #t1 ~= #t2 then return false end - for i, v in ipairs(t1) do - if t1[i] ~= t2[i] then return false end - end - return true -end - -local table_subtract = function(t1, t2) - if not t1 or next(t1) == nil then return nil end - if not t2 or next(t2) == nil then return t1 end - local res = {} - for _, v1 in ipairs(t1) do - local found = false - for _, v2 in ipairs(t2) do - if v1 == v2 then - found= true - break - end - end - if not found then - table.insert(res, v1) - end - end - return next(res) == nil and nil or res -end - -local map_subtract = function(t1, t2) - if not t1 or next(t1) == nil then return nil end - if not t2 or next(t2) == nil then return t1 end - local res = {} - for k1, v1 in pairs(t1) do - local found = false - for k2, v2 in ipairs(t2) do - if k1 == k2 and luci.util.serialize_data(v1) == luci.util.serialize_data(v2) then - found= true - break - end - end - if not found then - if v1 and type(v1) == "table" then - if next(v1) == nil then - res[k1] = { k = 'v' } - else - res[k1] = v1 - end - end - end - end - - return next(res) ~= nil and res or nil -end - --- return create_body, extra_network -local get_config = function(old_config, old_host_config, old_network_setting, image_config) - local config = old_config - if config.WorkingDir == image_config.WorkingDir then config.WorkingDir = "" end - if config.User == image_config.User then config.User = "" end - if table_equal(config.Cmd, image_config.Cmd) then config.Cmd = nil end - if table_equal(config.Entrypoint, image_config.Entrypoint) then config.Entrypoint = nil end - if table_equal(config.ExposedPorts, image_config.ExposedPorts) then config.ExposedPorts = nil end - config.Env = table_subtract(config.Env, image_config.Env) - config.Labels = table_subtract(config.Labels, image_config.Labels) - config.Volumes = map_subtract(config.Volumes, image_config.Volumes) - -- subtract ports exposed in image from container - if old_host_config.PortBindings and next(old_host_config.PortBindings) ~= nil then - config.ExposedPorts = {} - for p, v in pairs(old_host_config.PortBindings) do - config.ExposedPorts[p] = { HostPort=v[1] and v[1].HostPort } - end - end - - -- handle network config, we need only one network, extras need to network connect action - local network_setting = {} - local multi_network = false - local extra_network = {} - for k, v in pairs(old_network_setting) do - if multi_network then - extra_network[k] = v - else - network_setting[k] = v - end - multi_network = true - end - - -- handle hostconfig - local host_config = old_host_config - if host_config.PortBindings and next(host_config.PortBindings) == nil then host_config.PortBindings = nil end - host_config.LogConfig = nil - - -- merge configs - local create_body = config - create_body["HostConfig"] = host_config - create_body["NetworkingConfig"] = {EndpointsConfig = network_setting} - - return create_body, extra_network -end - -local upgrade = function(self, request) - _docker:clear_status() - -- get image name, image id, container name, configuration information - local container_info = self.containers:inspect({id = request.id}) - if container_info.code > 300 and type(container_info.body) == "table" then - return container_info - end - local image_name = container_info.body.Config.Image - if not image_name:match(".-:.+") then image_name = image_name .. ":latest" end - local old_image_id = container_info.body.Image - local container_name = container_info.body.Name:sub(2) - local old_config = container_info.body.Config - local old_host_config = container_info.body.HostConfig - local old_network_setting = container_info.body.NetworkSettings.Networks or {} - - local image_id, res = update_image(self, image_name) - if res and res.code > 300 then return res end - if image_id == old_image_id then - return {code = 305, body = {message = "Already up to date"}} - end - - _docker:append_status("Container: " .. "Stop" .. " " .. container_name .. "...") - res = self.containers:stop({name = container_name}) - if res and res.code < 305 then - _docker:append_status("done
") - else - return res - end - - _docker:append_status("Container: rename" .. " " .. container_name .. " to ".. container_name .. "_old ...") - res = self.containers:rename({name = container_name, query = { name = container_name .. "_old" }}) - if res and res.code < 300 then - _docker:append_status("done
") - else - return res - end - - -- handle config - local image_config = self.images:inspect({id = old_image_id}).body.Config - local create_body, extra_network = get_config(old_config, old_host_config, old_network_setting, image_config) - - -- create new container - _docker:append_status("Container: Create" .. " " .. container_name .. "...") - res = self.containers:create({name = container_name, body = create_body}) - if res and res.code > 300 then return res end - _docker:append_status("done
") - - -- extra networks need to network connect action - for k, v in pairs(extra_network) do - if v.IPAMConfig and next(v.IPAMConfig) == nil then v.IPAMConfig =nil end - if v.DriverOpts and next(v.DriverOpts) == nil then v.DriverOpts =nil end - if v.Aliases and next(v.Aliases) == nil then v.Aliases =nil end - - _docker:append_status("Networks: Connect" .. " " .. container_name .. "...") - res = self.networks:connect({id = k, body = {Container = container_name, EndpointConfig = v}}) - if res.code > 300 then return res end - - _docker:append_status("done
") - end - _docker:clear_status() - return res -end - -local duplicate_config = function (self, request) - local container_info = self.containers:inspect({id = request.id}) - if container_info.code > 300 and type(container_info.body) == "table" then return nil end - local old_image_id = container_info.body.Image - local old_config = container_info.body.Config - local old_host_config = container_info.body.HostConfig - local old_network_setting = container_info.body.NetworkSettings.Networks or {} - local image_config = self.images:inspect({id = old_image_id}).body.Config - return get_config(old_config, old_host_config, old_network_setting, image_config) -end - -_docker.new = function(option) - local option = option or {} - options = { - socket_path = option.socket_path or uci:get("dockerman", "local", "socket_path"), - debug = option.debug or uci:get("dockerman", "local", "debug") == 'true' and true or false, - debug_path = option.debug_path or uci:get("dockerman", "local", "debug_path") - } - local _new = docker.new(options) - _new.options.status_path = uci:get("dockerman", "local", "status_path") - _new.containers_upgrade = upgrade - _new.containers_duplicate_config = duplicate_config - return _new -end -_docker.options={} -_docker.options.status_path = uci:get("dockerman", "local", "status_path") - -_docker.append_status=function(self,val) - local file_docker_action_status=io.open(self.options.status_path, "a+") - file_docker_action_status:write(val) - file_docker_action_status:close() -end - -_docker.clear_status=function(self) - nixio.fs.remove(self.options.status_path) -end - -return _docker diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/docker_status.htm b/package/lean/luci-app-dockerman/luasrc/view/docker/docker_status.htm new file mode 100644 index 000000000..4d2c71468 --- /dev/null +++ b/package/lean/luci-app-dockerman/luasrc/view/docker/docker_status.htm @@ -0,0 +1,22 @@ + + +
+

+ <%:Collecting data...%> +

+
\ No newline at end of file diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm deleted file mode 100644 index b9de0408f..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm +++ /dev/null @@ -1,139 +0,0 @@ - - diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/dummyvalue.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/dummyvalue.htm deleted file mode 100644 index ac8a48aba..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/dummyvalue.htm +++ /dev/null @@ -1,13 +0,0 @@ -<%+cbi/valueheader%> -<% if self.href then %><% end -%> - <% - local val = self:cfgvalue(section) or self.default or "" - if not self.rawhtml then - write(pcdata(val)) - else - write(val) - end - %> -<%- if self.href then %><%end%> -" /> -<%+cbi/valuefooter%> diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinebutton.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinebutton.htm deleted file mode 100644 index b1b193257..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinebutton.htm +++ /dev/null @@ -1,7 +0,0 @@ -
- <% if self:cfgvalue(section) ~= false then %> - " type="submit"" <% if self.disable then %>disabled <% end %><%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.inputtitle or self.title)%> /> - <% else %> - - - <% end %> -
diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm deleted file mode 100644 index cfbf44a21..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm +++ /dev/null @@ -1,33 +0,0 @@ -
- <%- if self.title then -%> - - <%- end -%> - <%- if self.password then -%> - /> - <%- end -%> - 0, "data-choices", { self.keylist, self.vallist }) - %> /> - <%- if self.password then -%> -
- <% end %> -
diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xdynlist.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xdynlist.htm deleted file mode 100644 index 549c4ce31..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xdynlist.htm +++ /dev/null @@ -1,27 +0,0 @@ -<%+cbi/valueheader%> -> -<% - local vals = self:cfgvalue(section) or self.default or {} - for i=1, #vals + 1 do - local val = vals[i] - if (val and #val > 0) or (i == 1) then -%> - />
-<% end end %> - -<%+cbi/valuefooter%> diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xfvalue.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xfvalue.htm deleted file mode 100644 index 04f7bc2ee..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xfvalue.htm +++ /dev/null @@ -1,10 +0,0 @@ -<%+cbi/valueheader%> - /> - disabled <% end %><%= - attr("id", cbid) .. attr("name", cbid) .. attr("value", self.enabled or 1) .. - ifattr((self:cfgvalue(section) or self.default) == self.enabled, "checked", "checked") - %> /> - > -<%+cbi/valuefooter%> diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm deleted file mode 100644 index 7cfe8bf21..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm +++ /dev/null @@ -1,89 +0,0 @@ -<% - if not self.embedded then - %>
> - - - <% - end - - %>
<% - - if self.title and #self.title > 0 then - %>

<%=self.title%>

<% - end - - if self.description and #self.description > 0 then - %>
<%=self.description%>
<% - end - - self:render_children() - - %>
<% - - if self.message then - %>
<%=self.message%>
<% - end - - if self.errmessage then - %>
<%=self.errmessage%>
<% - end - - if not self.embedded then - if type(self.hidden) == "table" then - local k, v - for k, v in pairs(self.hidden) do - %><% - end - end - - local display_back = (self.redirect) - local display_cancel = (self.cancel ~= false and self.on_cancel) - local display_skip = (self.flow and self.flow.skip) - local display_submit = (self.submit ~= false) - local display_reset = (self.reset ~= false) - - if display_back or display_cancel or display_skip or display_submit or display_reset then - %>
<% - - if display_back then - %> <% - end - - if display_cancel then - local label = pcdata(self.cancel or translate("Cancel")) - %> <% - end - - if display_skip then - %> <% - end - - if display_submit then - local label = pcdata(self.submit or translate("Submit")) - %> <% - end - - if display_reset then - local label = pcdata(self.reset or translate("Reset")) - %> <% - end - - %>
<% - end - - %>
<% - end -%> - - diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/container.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/container.htm deleted file mode 100644 index 70e552444..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/container.htm +++ /dev/null @@ -1,25 +0,0 @@ -
- - - diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/container_file.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/container_file.htm deleted file mode 100644 index 07e6c7374..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/container_file.htm +++ /dev/null @@ -1,54 +0,0 @@ - -
- -
- -
-
- -
- -
-
-
- - -
-
- diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/logs.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/logs.htm deleted file mode 100644 index 6e189c66a..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/logs.htm +++ /dev/null @@ -1,10 +0,0 @@ -<% if self.title == translate("Docker Events") then %> -<%+header%> -<% end %> -

<%=self.title%>

-
- -
-<% if self.title == translate("Docker Events") then %> -<%+footer%> -<% end %> diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/overview.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/overview.htm deleted file mode 100644 index e9b443149..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/overview.htm +++ /dev/null @@ -1,281 +0,0 @@ - - -
-
-
-
-
- - Docker icon - - -
-
-
-

<%:Containers%>

-

- <%- if self.containers_total ~= "-" then -%><%- end -%> - <%=self.containers_running%> - /<%=self.containers_total%> - <%- if self.containers_total ~= "-" then -%><%- end -%> -

-
-
-
-
-
-
-
- - - - - -
-
-
-

<%:Images%>

-

- <%- if self.images_total ~= "-" then -%><%- end -%> - <%=self.images_used%> - /<%=self.images_total%> - <%- if self.images_total ~= "-" then -%><%- end -%> -

-
-
-
-
-
-
-
- - - - - - - - - -
-
-
-

<%:Networks%>

-

- <%- if self.networks_total ~= "-" then -%><%- end -%> - <%=self.networks_total%> - - <%- if self.networks_total ~= "-" then -%><%- end -%> -

-
-
-
-
-
-
-
- - - -
-
-
-

<%:Volumes%>

-

- <%- if self.volumes_total ~= "-" then -%><%- end -%> - <%=self.volumes_total%> - - <%- if self.volumes_total ~= "-" then -%><%- end -%> -

-
-
-
-
diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/resolv_container.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/resolv_container.htm deleted file mode 100644 index 38abc914c..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/resolv_container.htm +++ /dev/null @@ -1,94 +0,0 @@ - - -<%+cbi/valueheader%> - - -<%+cbi/valuefooter%> diff --git a/package/lean/luci-app-dockerman/luasrc/view/dockerman/stats.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/stats.htm deleted file mode 100644 index 2016181c5..000000000 --- a/package/lean/luci-app-dockerman/luasrc/view/dockerman/stats.htm +++ /dev/null @@ -1,60 +0,0 @@ - diff --git a/package/lean/luci-app-dockerman/po/zh-cn/docker.po b/package/lean/luci-app-dockerman/po/zh-cn/docker.po new file mode 100644 index 000000000..b95369aac --- /dev/null +++ b/package/lean/luci-app-dockerman/po/zh-cn/docker.po @@ -0,0 +1,39 @@ +msgid "" +msgstr "" +"Project-Id-Version: Luci ARP Bind\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-06-23 20:16+0800\n" +"PO-Revision-Date: 2015-06-23 20:17+0800\n" +"Last-Translator: coolsnowwolf \n" +"Language-Team: PandoraBox Team\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 1.8.1\n" +"X-Poedit-SourceCharset: UTF-8\n" + +msgid "Docker CE Container" +msgstr "Docker CE 容器" + +msgid "Open Portainer Docker Admin" +msgstr "打开 Portainer Docker 管理页面" + +msgid "Docker is a set of platform-as-a-service (PaaS) products that use OS-level virtualization to deliver software in packages called containers." +msgstr "Docker是一组平台即服务(platform-as-a-service,PaaS)产品,它使用操作系统级容器虚拟化来交付软件包。" + +msgid "Enable WAN access Dokcer" +msgstr "允许 WAN 访问 Dokcer" + +msgid "Enable WAN access docker mapped ports" +msgstr "允许 WAN 访问 Dokcer 映射后的端口(易受攻击!)。

推荐禁用该选项后,用系统防火墙选择性映射 172.17.0.X:XX 端口到 WAN" + +msgid "Docker Readme First" +msgstr "Docker 初始化无脑配置教程" + +msgid "Download DockerReadme.pdf" +msgstr "下载 Docker 初始化无脑配置教程" + +msgid "Please download DockerReadme.pdf to read when first-running" +msgstr "初次在OpenWrt中运行Docker必读(只需执行一次流程)" \ No newline at end of file diff --git a/package/lean/luci-app-dockerman/po/zh-cn/dockerman.po b/package/lean/luci-app-dockerman/po/zh-cn/dockerman.po deleted file mode 100644 index 9737507ca..000000000 --- a/package/lean/luci-app-dockerman/po/zh-cn/dockerman.po +++ /dev/null @@ -1,359 +0,0 @@ -msgid "Containers" -msgstr "容器" - -msgid "Images" -msgstr "镜像" - -msgid "Networks" -msgstr "网络" - -msgid "Volumes" -msgstr "存储卷" - -msgid "Events" -msgstr "事件" - -msgid "Docker Contaienr" -msgstr "Docker 容器" - -msgid "Start" -msgstr "启动" - -msgid "Restart" -msgstr "重启" - -msgid "Stop" -msgstr "停止" - -msgid "Upgrade" -msgstr "升级容器" - -msgid "Duplicate" -msgstr "复制容器" - -msgid "Remove" -msgstr "移除" - -msgid "Name" -msgstr "名称" - -msgid "Image" -msgstr "镜像" - -msgid "Status" -msgstr "状态" - -msgid "Created" -msgstr "创建时间" - -msgid "Start Time" -msgstr "启动时间" - -msgid "Healthy" -msgstr "健康" - -msgid "Restart Policy" -msgstr "重启策略" - -msgid "Update" -msgstr "更新" - -msgid "Device(--device)" -msgstr "设备(--device)" - -msgid "Mount/Volume" -msgstr "挂载/存储卷" - -msgid "Command" -msgstr "启动命令" - -msgid "Setting" -msgstr "设置" - -msgid "Driver" -msgstr "驱动" - -msgid "Env" -msgstr "环境变量" - -msgid "Ports" -msgstr "端口" - -msgid "Links" -msgstr "链接" - -msgid "Disconnect" -msgstr "断开" - -msgid "Connect Network" -msgstr "连接网络" - -msgid "Connect" -msgstr "连接" - -msgid "Info" -msgstr "信息" - -msgid "CPUs" -msgstr "CPU数量" - -msgid "Number of CPUs. Number is a fractional number. 0.000 means no limit." -msgstr "CPU数量,数字是小数,0.000表示没有限制。" - -msgid "CPU Shares Weight" -msgstr "CPU份额权重" - -msgid "CPU shares relative weight, if 0 is set, the system will ignore the value and use the default of 1024." -msgstr "CPU份额相对权重,如果设置为0,则系统将忽略该值,并使用默认值1024。" - -msgid "Memory" -msgstr "内存" - -msgid "Memory limit (format: []). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M." -msgstr "内存限制 (格式: <容量>[<单位>]). 数字是一个正整数。单位可以是b,k,m或g之一。最小为4M。" - -msgid "Block IO Weight" -msgstr "IO 权重" - -msgid "Block IO weight (relative weight) accepts a weight value between 10 and 1000." -msgstr "IO 权重 (相对权重) 接受10到1000之间的权重值。" - -msgid "Container Logs" -msgstr "容器日志" - -msgid "RepoTags" -msgstr "标签" - -msgid "Size" -msgstr "大小" - -msgid "Force Remove" -msgstr "强制移除" - -msgid "Subnet" -msgstr "子网络" - -msgid "Gateway" -msgstr "网关" - -msgid "New" -msgstr "新建" - -msgid "Resolv CLI" -msgstr "解析命令行" - -msgid "Docker Image" -msgstr "Docker 镜像" - -msgid "User(-u)" -msgstr "用户(-u)" - -msgid "New Container" -msgstr "新容器" - -msgid "Container Name" -msgstr "容器名称" - -msgid "Interactive (-i)" -msgstr "互动式 (-i)" - -msgid "Always pull image first" -msgstr "始终先拉取镜像" - -msgid "Privileged" -msgstr "特权模式(--privileged)" - -msgid "IPv4 Address" -msgstr "IPv4 地址" - -msgid "Links with other containers" -msgstr "与其他容器的链接(--link)" - -msgid "Environmental Variable(-e)" -msgstr "环境变量(-e)" - -msgid "Bind Mount(-v)" -msgstr "挂载(-v)" - -msgid "Exposed Ports(-p)" -msgstr "暴露端口(-p)" - -msgid "Run command" -msgstr "运行命令" - -msgid "Advance" -msgstr "高级" - -msgid "Mount tmpfs directory" -msgstr "挂载tmpfs到容器内部目录" - -msgid "New Network" -msgstr "新网络" - -msgid "Network Name" -msgstr "网络名称" - -msgid "Parent Interface" -msgstr "父接口" - -msgid "Macvlan Mode" -msgstr "Macvlan模式" - -msgid "Ipvlan Mode" -msgstr "Ipvlan模式" - -msgid "Ingress network is the network which provides the routing-mesh in swarm mode." -msgstr "Ingress网络是在群集模式下提供路由网的网络。" - -msgid "Options" -msgstr "选项" - -msgid "Restrict external access to the network" -msgstr "限制外部访问网络" - -msgid "IP range" -msgstr "IP范围" - -msgid "Exclude IPs" -msgstr "排除IP" - -msgid "Enable IPv6" -msgstr "启用IPv6" - -msgid "IPv6 Subnet" -msgstr "IPv6子网" - -msgid "IPv6 Gateway" -msgstr "IPv6网关" - -msgid "Docker Version" -msgstr "Docker版本" - -msgid "Api Version" -msgstr "API版本" - -msgid "Total Memory" -msgstr "总内存" - -msgid "Docker Root Dir" -msgstr "Docker根目录" - -msgid "Index Server Address" -msgstr "默认服务器地址" - -msgid "Socket Path" -msgstr "Socket路径" - -msgid "Action Status Tempfile Path" -msgstr "Docker 动作状态的临时文件路径" - -msgid "Where you want to save the docker status file" -msgstr "保存docker status文件的位置" - -msgid "Enable WAN access Dokcer" -msgstr "允许 WAN 访问 Dokcer" - -msgid "Enable WAN access docker mapped ports (need reload Docker-ce service)" -msgstr "允许 WAN 访问 Dokcer 映射后的端口(易受攻击!)。

如已更改此选项,需要点击应用并保存后重启docker服务。
推荐禁用该选项后,用系统防火墙选择性映射 172.17.0.X:XX 端口到 WAN" - -msgid "Enable Debug" -msgstr "启用调试" - -msgid "For debug, It shows all docker API actions of luci-app-dockerman in Debug Tempfile Path" -msgstr "用于调试,在调试临时文件路径中显示 luci-app-dockerman 的所有 Docker API 操作" - -msgid "Debug Tempfile Path" -msgstr "调试临时文件路径" - -msgid "Where you want to save the debug tempfile" -msgstr "保存调试临时文件的位置" - -msgid "Edit" -msgstr "编辑" - -msgid "Stats" -msgstr "状态" - -msgid "Logs" -msgstr "日志" - -msgid "Network TX/RX" -msgstr "网络发送/接收" - -msgid "CPU Useage" -msgstr "CPU用量" - -msgid "Memory Useage" -msgstr "内存用量" - -msgid "Docker Container" -msgstr "Docker 容器" - -msgid "Overview" -msgstr "概况" - -msgid "Pull Image" -msgstr "拉取镜像" - -msgid "Pull" -msgstr "拉取" - -msgid "Command line" -msgstr "输入命令行" - -msgid "Plese input command line:" -msgstr "请输入 docker run/create ... 命令行:" - -msgid "Network Name" -msgstr "网络名" - -msgid "Set custom DNS servers" -msgstr "自定义 DNS 服务器" - -msgid "The user that commands are run as inside the container.(format: name|uid[:group|gid])" -msgstr "容器内部执行命令的用户(组), 格式: UID:GID" - -msgid "Set environment variables to inside the container" -msgstr "容器内部环境变量" - -msgid "Bind mount a volume" -msgstr "绑定挂载" - -msgid "Publish container's port(s) to the host" -msgstr "将容器的端口发布到宿主" - -msgid "Add host device to the container" -msgstr "添加宿主设备到容器内部" - -msgid "Device" -msgstr "设备" - -msgid "Finish Time" -msgstr "结束时间" - -msgid "Command line Error" -msgstr "命令行错误" - -msgid "Host Name" -msgstr "主机名称" - -msgid "The hostname to use for the container" -msgstr "容器使用的主机名" - -msgid "File" -msgstr "文件" - -msgid "Upload" -msgstr "上传" - -msgid "Download" -msgstr "下载" - -msgid "Path" -msgstr "路径" - -msgid "Upload Error" -msgstr "上传错误" - -msgid "Upload Success" -msgstr "上传成功" diff --git a/package/lean/luci-app-dockerman/root/etc/config/dockerd b/package/lean/luci-app-dockerman/root/etc/config/dockerd new file mode 100644 index 000000000..b73c0a3e3 --- /dev/null +++ b/package/lean/luci-app-dockerman/root/etc/config/dockerd @@ -0,0 +1,4 @@ + +config docker + option wan_mode '0' + diff --git a/package/lean/luci-app-dockerman/root/etc/config/dockerman b/package/lean/luci-app-dockerman/root/etc/config/dockerman deleted file mode 100644 index 7ed611663..000000000 --- a/package/lean/luci-app-dockerman/root/etc/config/dockerman +++ /dev/null @@ -1,6 +0,0 @@ -config section 'local' - option socket_path '/var/run/docker.sock' - option status_path '/tmp/.docker_action_status' - option wan_mode 'false' - option debug_path '/tmp/.docker_debug' - option debug 'false' diff --git a/package/lean/luci-app-dockerman/root/etc/docker-init b/package/lean/luci-app-dockerman/root/etc/docker-init index 45b9769a5..9bade865f 100755 --- a/package/lean/luci-app-dockerman/root/etc/docker-init +++ b/package/lean/luci-app-dockerman/root/etc/docker-init @@ -23,3 +23,4 @@ w fi echo "y" | mkfs.ext4 /dev/sda$partid + diff --git a/package/lean/luci-app-dockerman/root/etc/docker-web b/package/lean/luci-app-dockerman/root/etc/docker-web new file mode 100755 index 000000000..010ab1eac --- /dev/null +++ b/package/lean/luci-app-dockerman/root/etc/docker-web @@ -0,0 +1,3 @@ +#!/bin/sh + +docker run -d --restart=always --name="portainer" -p 9999:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer \ No newline at end of file diff --git a/package/lean/luci-app-dockerman/root/etc/init.d/dockerd b/package/lean/luci-app-dockerman/root/etc/init.d/dockerd index fb3f5e6dd..5d6f36bf2 100755 --- a/package/lean/luci-app-dockerman/root/etc/init.d/dockerd +++ b/package/lean/luci-app-dockerman/root/etc/init.d/dockerd @@ -5,9 +5,9 @@ START=25 start_service() { local nofile=$(cat /proc/sys/fs/nr_open) - local wanmode=$(uci get dockerman.local.wan_mode) - - if [ $wanmode = "true" ] ;then + local wanmode=$(uci get dockerd.@docker[0].wan_mode) + + if [ $wanmode = "1" ] ;then dockerwan=" " else dockerwan="--iptables=false" @@ -18,5 +18,5 @@ start_service() { procd_set_param command /usr/bin/dockerd $dockerwan procd_set_param limits nofile="${nofile} ${nofile}" procd_close_instance - + } diff --git a/package/lean/luci-app-dockerman/root/etc/uci-defaults/docker b/package/lean/luci-app-dockerman/root/etc/uci-defaults/docker new file mode 100755 index 000000000..e03f47783 --- /dev/null +++ b/package/lean/luci-app-dockerman/root/etc/uci-defaults/docker @@ -0,0 +1,11 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@dockerd[-1] + add ucitrack dockerd + set ucitrack.@dockerd[-1].init=dockerd + commit ucitrack +EOF + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/package/lean/luci-app-dockerman/root/www/DockerReadme.pdf b/package/lean/luci-app-dockerman/root/www/DockerReadme.pdf new file mode 100644 index 000000000..8a9a94b83 Binary files /dev/null and b/package/lean/luci-app-dockerman/root/www/DockerReadme.pdf differ