diff --git a/package/lean/luci-app-dockerman/Makefile b/package/lean/luci-app-dockerman/Makefile index 75f17a547..3e6b10dd3 100644 --- a/package/lean/luci-app-dockerman/Makefile +++ b/package/lean/luci-app-dockerman/Makefile @@ -1,11 +1,18 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-dockerman -PKG_VERSION:=v0.2.2 +PKG_VERSION:=v0.3.0 PKG_RELEASE:=beta PKG_MAINTAINER:=lisaac -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) -PKG_LICENSE:=Apache-2.0 +PKG_LICENSE:=AGPL-3.0 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/lisaac/luci-app-dockerman.git +PKG_SOURCE_VERSION:=$(PKG_VERSION) + +PKG_SOURCE_SUBDIR:=$(PKG_NAME) +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR)-$(PKG_VERSION).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) include $(INCLUDE_DIR)/package.mk @@ -23,6 +30,7 @@ define Package/$(PKG_NAME)/description endef define Build/Prepare + tar -xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(BUILD_DIR) endef define Build/Compile @@ -34,12 +42,16 @@ rm -fr /tmp/luci-indexcache /tmp/luci-modulecache endef define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/usr/lib/lua/luci - cp -pR ./luasrc/* $(1)/usr/lib/lua/luci $(INSTALL_DIR) $(1)/ - cp -pR ./root/* $(1)/ + cp -pR $(PKG_BUILD_DIR)/root/* $(1)/ + # $(INSTALL_DIR) $(1)/www + # cp -pR $(PKG_BUILD_DIR)/htdoc/* $(1)/www + $(INSTALL_DIR) $(1)/usr/lib/lua/luci + cp -pR $(PKG_BUILD_DIR)/luasrc/* $(1)/usr/lib/lua/luci/ $(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n - po2lmo ./po/zh-cn/dockerman.po $(1)/usr/lib/lua/luci/i18n/dockerman.zh-cn.lmo + $(foreach po, $(shell find $(PKG_BUILD_DIR)/po/*/*.po),\ + po2lmo $(po) $(1)/usr/lib/lua/luci/i18n/dockerman.$(shell echo $(po) | awk -F'/' '{print $$(NF-1)}').lmo;) + #po2lmo $(PKG_BUILD_DIR)/po/zh-cn/dockerman.po $(1)/usr/lib/lua/luci/i18n/dockerman.zh-cn.lmo endef $(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lean/luci-app-dockerman/luasrc/controller/dockerman.lua b/package/lean/luci-app-dockerman/luasrc/controller/dockerman.lua index 794224f0a..cd8060764 100644 --- a/package/lean/luci-app-dockerman/luasrc/controller/dockerman.lua +++ b/package/lean/luci-app-dockerman/luasrc/controller/dockerman.lua @@ -11,20 +11,22 @@ module("luci.controller.dockerman",package.seeall) function index() entry({"admin", "services","docker"}, firstchild(), "Docker", 40).dependent = false - entry({"admin","services","docker","overview"},cbi("docker/overview"),_("Overview"),0).leaf=true + entry({"admin","services","docker","overview"},cbi("dockerman/overview"),_("Overview"),0).leaf=true - local socket = luci.model.uci.cursor():get("docker", "local", "socket_path") + 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("docker/containers"),_("Containers"),1).leaf=true - entry({"admin","services","docker","images"},form("docker/images"),_("Images"),2).leaf=true - entry({"admin","services","docker","networks"},form("docker/networks"),_("Networks"),3).leaf=true - entry({"admin","services","docker","volumes"},form("docker/volumes"),_("Volumes"),4).leaf=true + 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("docker/newcontainer")).leaf=true - entry({"admin","services","docker","newnetwork"},form("docker/newnetwork")).leaf=true - entry({"admin","services","docker","container"},form("docker/container")).leaf=true + 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 @@ -35,7 +37,7 @@ function action_events() local dk = docker.new() local query ={} query["until"] = os.time() - local events = dk:events(nil, query) + 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") @@ -45,7 +47,7 @@ function action_events() 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("docker/logs", {self={syslog = logs, title="Docker Events"}}) + luci.template.render("dockerman/logs", {self={syslog = logs, title="Docker Events"}}) end local calculate_cpu_percent = function(d) @@ -94,9 +96,9 @@ end function action_get_container_stats(container_id) if container_id then local dk = docker.new() - local response = dk.containers:inspect(container_id) + local response = dk.containers:inspect({id = container_id}) if response.code == 200 and response.body.State.Running then - response = dk.containers:stats(container_id, {stream=false}) + 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) @@ -136,7 +138,7 @@ function action_get_container_stats(container_id) end function action_confirm() - local status_path=luci.model.uci.cursor():get("docker", "local", "status_path") + local status_path=luci.model.uci.cursor():get("dockerman", "local", "status_path") local data = nixio.fs.readfile(status_path) if data then code = 202 @@ -151,3 +153,49 @@ function action_confirm() 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/container.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua similarity index 90% rename from package/lean/luci-app-dockerman/luasrc/model/cbi/docker/container.lua rename to package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua index d27c52f95..fbb87615d 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/container.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua @@ -12,7 +12,7 @@ local action = arg[2] or "info" local images, networks, containers_info if not container_id then return end -local res = dk.containers:inspect(container_id) +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 @@ -110,9 +110,9 @@ local start_stop_remove = function(m, cmd) docker:append_status("Containers: " .. cmd .. " " .. container_id .. "...") local res if cmd ~= "upgrade" then - res = dk.containers[cmd](dk, container_id) + res = dk.containers[cmd](dk, {id = container_id}) else - res = dk.containers_upgrade(dk, container_id) + 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)) @@ -128,11 +128,11 @@ local start_stop_remove = function(m, cmd) end m=SimpleForm("docker", container_info.Name:sub(2), translate("Docker Container") ) -m.template = "docker/cbi/xsimpleform" +m.template = "dockerman/cbi/xsimpleform" m.redirect = luci.dispatcher.build_url("admin/services/docker/containers") --- m:append(Template("docker/container")) +-- m:append(Template("dockerman/container")) docker_status = m:section(SimpleSection) -docker_status.template="docker/apply_widget" +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 @@ -141,35 +141,35 @@ 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" +action_section.template = "cbi/nullsection" btnstart=action_section:option(Button, "_start") -btnstart.template="docker/cbi/inlinebutton" +btnstart.template = "dockerman/cbi/inlinebutton" btnstart.inputtitle=translate("Start") btnstart.inputstyle = "apply" btnstart.forcewrite = true btnrestart=action_section:option(Button, "_restart") -btnrestart.template="docker/cbi/inlinebutton" +btnrestart.template = "dockerman/cbi/inlinebutton" btnrestart.inputtitle=translate("Restart") btnrestart.inputstyle = "reload" btnrestart.forcewrite = true btnstop=action_section:option(Button, "_stop") -btnstop.template="docker/cbi/inlinebutton" +btnstop.template = "dockerman/cbi/inlinebutton" btnstop.inputtitle=translate("Stop") btnstop.inputstyle = "reset" btnstop.forcewrite = true btnupgrade=action_section:option(Button, "_upgrade") -btnupgrade.template="docker/cbi/inlinebutton" +btnupgrade.template = "dockerman/cbi/inlinebutton" btnupgrade.inputtitle=translate("Upgrade") btnupgrade.inputstyle = "reload" btnstop.forcewrite = true btnduplicate=action_section:option(Button, "_duplicate") -btnduplicate.template="docker/cbi/inlinebutton" +btnduplicate.template = "dockerman/cbi/inlinebutton" btnduplicate.inputtitle=translate("Duplicate") btnduplicate.inputstyle = "add" btnstop.forcewrite = true btnremove=action_section:option(Button, "_remove") -btnremove.template="docker/cbi/inlinebutton" +btnremove.template = "dockerman/cbi/inlinebutton" btnremove.inputtitle=translate("Remove") btnremove.inputstyle = "remove" btnremove.forcewrite = true @@ -194,7 +194,7 @@ btnduplicate.write = function(self, section) end tab_section = m:section(SimpleSection) -tab_section.template="docker/container" +tab_section.template = "dockerman/container" if action == "info" then m.submit = false @@ -302,7 +302,7 @@ if action == "info" then end dv_opts.render = function(self, section, scope) if table_info[section]._key==translate("Connect Network") then - self.template="cbi/value" + self.template = "cbi/value" self.keylist = {} self.vallist = {} self.placeholder = "10.1.1.254" @@ -324,7 +324,7 @@ if action == "info" then self.template = "cbi/button" Button.render(self, section, scope) else - self.template = "docker/cbi/dummyvalue" + self.template = "dockerman/cbi/dummyvalue" self.default="" DummyValue.render(self, section, scope) end @@ -336,16 +336,16 @@ if action == "info" then if section == "01name" then docker:append_status("Containers: rename " .. container_id .. "...") local new_name = table_info[section]._value - res = dk.containers:rename(container_id,{name=new_name}) + 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(container_id, nil, {RestartPolicy = {Name = new_restart}}) + 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(leave_network, nil, {Container = 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 @@ -358,7 +358,7 @@ if action == "info" then } or nil end docker:append_status("Network: connect " .. connect_network .. container_id .. "...") - res = dk.networks:connect(connect_network, nil, {Container = container_id, EndpointConfig= network_opiton}) + 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)) @@ -370,7 +370,7 @@ if action == "info" then -- info end elseif action == "edit" then - editsection= m:section(SimpleSection) + 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 @@ -420,7 +420,7 @@ elseif action == "edit" then } docker:clear_status() docker:append_status("Containers: update " .. container_id .. "...") - local res = dk.containers:update(container_id, nil, request_body) + 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 @@ -429,31 +429,37 @@ elseif action == "edit" then 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 - logsection= m:section(SimpleSection) + local logsection= m:section(SimpleSection) local logs = "" local query ={ stdout = 1, stderr = 1, tail = 1000 } - local logs = dk.containers:logs(container_id, query) + 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="docker/logs" + logsection.template = "dockerman/logs" m.submit = false - m.reset = false + m.reset = false elseif action == "stats" then - local response = dk.containers:top(container_id, {ps_args="-aux"}) + 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(container_id) + response = dk.containers:top({id = container_id}) if response.code == 200 then container_top=response.body end @@ -463,7 +469,7 @@ elseif action == "stats" then container_top=response.body stat_section = m:section(SimpleSection) stat_section.container_id = container_id - stat_section.template="docker/stats" + 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%" diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/containers.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua similarity index 92% rename from package/lean/luci-app-dockerman/luasrc/model/cbi/docker/containers.lua rename to package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua index dc4742297..8c95ed77d 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/containers.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua @@ -14,7 +14,7 @@ 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(nil, {all=true}) +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 @@ -68,12 +68,12 @@ local c_lists = get_containers() -- list Containers -- m = Map("docker", translate("Docker")) m = SimpleForm("docker", translate("Docker")) -m.template = "docker/cbi/xsimpleform" +m.template = "dockerman/cbi/xsimpleform" m.submit=false m.reset=false docker_status = m:section(SimpleSection) -docker_status.template="docker/apply_widget" +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 @@ -91,7 +91,7 @@ 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="docker/cbi/dummyvalue" +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 @@ -103,7 +103,7 @@ 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="docker/cbi/dummyvalue" +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)) @@ -131,12 +131,11 @@ local start_stop_remove = function(m,cmd) end end if #c_selected >0 then - -- luci.util.perror(dk.options.status_path) 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, 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).. "
") @@ -156,26 +155,26 @@ action_section.template="cbi/nullsection" btnnew=action_section:option(Button, "_new") btnnew.inputtitle= translate("New") -btnnew.template="docker/cbi/inlinebutton" +btnnew.template = "dockerman/cbi/inlinebutton" btnnew.inputstyle = "add" btnnew.forcewrite = true btnstart=action_section:option(Button, "_start") -btnstart.template="docker/cbi/inlinebutton" +btnstart.template = "dockerman/cbi/inlinebutton" btnstart.inputtitle=translate("Start") btnstart.inputstyle = "apply" btnstart.forcewrite = true btnrestart=action_section:option(Button, "_restart") -btnrestart.template="docker/cbi/inlinebutton" +btnrestart.template = "dockerman/cbi/inlinebutton" btnrestart.inputtitle=translate("Restart") btnrestart.inputstyle = "reload" btnrestart.forcewrite = true btnstop=action_section:option(Button, "_stop") -btnstop.template="docker/cbi/inlinebutton" +btnstop.template = "dockerman/cbi/inlinebutton" btnstop.inputtitle=translate("Stop") btnstop.inputstyle = "reset" btnstop.forcewrite = true btnremove=action_section:option(Button, "_remove") -btnremove.template="docker/cbi/inlinebutton" +btnremove.template = "dockerman/cbi/inlinebutton" btnremove.inputtitle=translate("Remove") btnremove.inputstyle = "remove" btnremove.forcewrite = true diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/images.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua similarity index 83% rename from package/lean/luci-app-dockerman/luasrc/model/cbi/docker/images.lua rename to package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua index 9935f3fa8..1f8902eab 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/images.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua @@ -11,7 +11,7 @@ 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(nil, {all=true}) +res = dk.containers:list({query = {all=true}}) if res.code <300 then containers = res.body else return end function get_images() @@ -45,7 +45,7 @@ local image_list = get_images() -- m = Map("docker", translate("Docker")) m = SimpleForm("docker", translate("Docker")) -m.template = "docker/cbi/xsimpleform" +m.template = "dockerman/cbi/xsimpleform" m.submit=false m.reset=false @@ -53,14 +53,17 @@ 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="docker/cbi/inlinevalue" +tag_name.template = "dockerman/cbi/inlinevalue" tag_name.placeholder="hello-world:latest" local registry = pull_section:option(Value, "_registry") -registry.template="docker/cbi/inlinevalue" -registry:value("index.docker.io", "DockerHub") +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="docker/cbi/inlinebutton" +action_pull.template = "dockerman/cbi/inlinebutton" action_pull.inputstyle = "add" tag_name.write = function(self, section,value) local hastag = value:find(":") @@ -80,19 +83,21 @@ action_pull.write = function(self, section) if not tmp then _,_,server = server:find("([%.%w%-%_]+)") end - local json_stringify = luci.json and luci.json.encode or luci.jsonc.stringify - if tag then + 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(nil, {fromImage=tag,_header={["X-Registry-Auth"]=x_auth}}) + 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 - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/images")) + 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")) @@ -126,11 +131,9 @@ local remove_action = function(force) docker:clear_status() for _,img in ipairs(image_selected) do docker:append_status("Images: " .. "remove" .. " " .. img .. "...") - local query_body ={} - if force then - query_body.force = true - end - local msg = dk.images["remove"](dk, img, query_body) + 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 @@ -144,7 +147,7 @@ local remove_action = function(force) end docker_status = m:section(SimpleSection) -docker_status.template="docker/apply_widget" +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 @@ -155,7 +158,7 @@ action.template="cbi/nullsection" btnremove = action:option(Button, "remove") btnremove.inputtitle= translate("Remove") -btnremove.template="docker/cbi/inlinebutton" +btnremove.template = "dockerman/cbi/inlinebutton" btnremove.inputstyle = "remove" btnremove.forcewrite = true btnremove.write = function(self, section) @@ -164,7 +167,7 @@ end btnforceremove = action:option(Button, "forceremove") btnforceremove.inputtitle= translate("Force Remove") -btnforceremove.template="docker/cbi/inlinebutton" +btnforceremove.template = "dockerman/cbi/inlinebutton" btnforceremove.inputstyle = "remove" btnforceremove.forcewrite = true btnforceremove.write = function(self, section) diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/networks.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua similarity index 93% rename from package/lean/luci-app-dockerman/luasrc/model/cbi/docker/networks.lua rename to package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua index 9337e96b3..ae8ed0bac 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/networks.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua @@ -36,7 +36,7 @@ end local network_list = get_networks() -- m = Map("docker", translate("Docker")) m = SimpleForm("docker", translate("Docker")) -m.template = "docker/cbi/xsimpleform" +m.template = "dockerman/cbi/xsimpleform" m.submit=false m.reset=false @@ -44,7 +44,7 @@ network_table = m:section(Table, network_list, translate("Networks")) network_table.nodescr=true network_selecter = network_table:option(Flag, "_selected","") -network_selecter.template = "docker/cbi/xfvalue" +network_selecter.template = "dockerman/cbi/xfvalue" network_id = network_table:option(DummyValue, "_id", translate("ID")) network_selecter.disabled = 0 network_selecter.enabled = 1 @@ -68,7 +68,7 @@ network_selecter.write = function(self, section, value) end docker_status = m:section(SimpleSection) -docker_status.template="docker/apply_widget" +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 @@ -78,7 +78,7 @@ action.rowcolors=false action.template="cbi/nullsection" btnnew=action:option(Button, "_new") btnnew.inputtitle= translate("New") -btnnew.template="docker/cbi/inlinebutton" +btnnew.template = "dockerman/cbi/inlinebutton" btnnew.notitle=true btnnew.inputstyle = "add" btnnew.forcewrite = true @@ -87,7 +87,7 @@ btnnew.write = function(self, section) end btnremove = action:option(Button, "_remove") btnremove.inputtitle= translate("Remove") -btnremove.template="docker/cbi/inlinebutton" +btnremove.template = "dockerman/cbi/inlinebutton" btnremove.inputstyle = "remove" btnremove.forcewrite = true btnremove.write = function(self, section) @@ -105,7 +105,7 @@ btnremove.write = function(self, section) docker:clear_status() for _,net in ipairs(network_selected) do docker:append_status("Networks: " .. "remove" .. " " .. net .. "...") - local res = dk.networks["remove"](dk, 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 diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/newcontainer.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua similarity index 95% rename from package/lean/luci-app-dockerman/luasrc/model/cbi/docker/newcontainer.lua rename to package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua index 6e2cc689d..f92a1aaae 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/newcontainer.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua @@ -13,7 +13,7 @@ local create_body = {} local images = dk.images:list().body local networks = dk.networks:list().body -local containers = dk.containers:list(nil, {all=true}).body +local containers = dk.containers:list({query = {all=true}}).body local is_quot_complete = function(str) if not str then return true end @@ -158,7 +158,7 @@ if cmd_line and cmd_line:match("^docker.+") then end elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then local container_id = cmd_line:match("^duplicate/(.+)") - create_body = dk:containers_duplicate_config(container_id) + 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 @@ -204,14 +204,14 @@ elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then end local m = SimpleForm("docker", translate("Docker")) -m.template = "docker/cbi/xsimpleform" +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="docker/apply_widget" +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 @@ -221,7 +221,7 @@ s.anonymous = true local d = s:option(DummyValue,"cmd_line", translate("Resolv CLI")) d.rawhtml = true -d.template = "docker/resolv_container" +d.template = "dockerman/resolv_container" d = s:option(Value, "name", translate("Container Name")) d.rmempty = true @@ -279,14 +279,14 @@ 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 = "docker/cbi/xdynlist" +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 = "docker/cbi/xdynlist" +d.template = "dockerman/cbi/xdynlist" d.placeholder = "8.8.8.8" d.rmempty = true d.default = default_config.dns or nil @@ -297,19 +297,19 @@ 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 = "docker/cbi/xdynlist" +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 = "docker/cbi/xdynlist" +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 = "docker/cbi/xdynlist" +d_ports.template = "dockerman/cbi/xdynlist" d_ports.placeholder = "2200:22/tcp" d_ports.rmempty = true d_ports.default = default_config.port or nil @@ -325,20 +325,20 @@ d.disabled = 0 d.enabled = 1 d.default = default_config.advance or 0 -d = s:option(Value, "hostname", translate("Host Name")) +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 = "docker/cbi/xdynlist" +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 = "docker/cbi/xdynlist" +d.template = "dockerman/cbi/xdynlist" d.placeholder = "/run:rw,noexec,nosuid,size=65536k" d.rmempty = true d:depends("advance", 1) @@ -538,10 +538,10 @@ m.handle = function(self, state, data) end local pull_image = function(image) local server = "index.docker.io" - local json_stringify = luci.json and luci.json.encode or luci.jsonc.stringify + 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(nil, {fromImage=image,_header={["X-Registry-Auth"]=x_auth}}) + 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 @@ -566,7 +566,7 @@ m.handle = function(self, state, data) end docker:append_status("Container: " .. "create" .. " " .. name .. "...") - local res = dk.containers:create(name, nil, create_body) + 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")) diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/newnetwork.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua similarity index 96% rename from package/lean/luci-app-dockerman/luasrc/model/cbi/docker/newnetwork.lua rename to package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua index c599f0a66..650667e6e 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/newnetwork.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua @@ -9,11 +9,11 @@ local docker = require "luci.model.docker" local dk = docker.new() m = SimpleForm("docker", translate("Docker")) -m.template = "docker/cbi/xsimpleform" +m.template = "dockerman/cbi/xsimpleform" m.redirect = luci.dispatcher.build_url("admin", "services","docker", "networks") docker_status = m:section(SimpleSection) -docker_status.template="docker/apply_widget" +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 @@ -60,7 +60,7 @@ d.default = 0 d:depends("dirver", "overlay") d = s:option(DynamicList, "options", translate("Options")) -d.template = "docker/cbi/xdynlist" +d.template = "dockerman/cbi/xdynlist" d.rmempty = true d.placeholder="com.docker.network.driver.mtu=1500" @@ -86,7 +86,7 @@ d.placeholder="10.1.1.0/24" d.datatype="ip4addr" d = s:option(DynamicList, "aux_address", translate("Exclude IPs")) -d.template = "docker/cbi/xdynlist" +d.template = "dockerman/cbi/xdynlist" d.rmempty = true d.placeholder="my-route=10.1.1.1" @@ -191,7 +191,7 @@ m.handle = function(self, state, data) end docker:append_status("Network: " .. "create" .. " " .. create_body.Name .. "...") - local res = dk.networks:create(nil, nil, create_body) + 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")) diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/overview.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua similarity index 74% rename from package/lean/luci-app-dockerman/luasrc/model/cbi/docker/overview.lua rename to package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua index b24dc004b..2655e73bf 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/overview.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua @@ -8,17 +8,17 @@ 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 + 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("docker", translate("Docker")) +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='-'} @@ -41,13 +41,14 @@ s.containers_total = '-' s.images_total = '-' s.networks_total = '-' s.volumes_total = '-' -local socket = luci.model.uci.cursor():get("docker", "local", "socket_path") +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(nil, {all=true}).body - -- local images_list = dk.images:list().body - local volumes_list = dk.volumes:list().body.Volumes - local networks_list = dk.networks:list().body + 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 @@ -55,27 +56,27 @@ if nixio.fs.access(socket) and (require "luci.model.docker").new():_ping().code 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 = tostring(byte_format(docker_info.body.MemTotal)) + 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.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.images_used = tostring(s.images_used) s.containers_total = tostring(docker_info.body.Containers) - s.images_total = tostring(docker_info.body.Images) + s.images_total = tostring(#images_list) s.networks_total = tostring(#networks_list) s.volumes_total = tostring(#volumes_list) end -s.template = "docker/overview" +s.template = "dockerman/overview" s = m:section(NamedSection, "local", "section", translate("Setting")) diff --git a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/volumes.lua b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua similarity index 94% rename from package/lean/luci-app-dockerman/luasrc/model/cbi/docker/volumes.lua rename to package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua index 06ac409a7..9c3870732 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/cbi/docker/volumes.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua @@ -11,7 +11,7 @@ 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(nil, {all=true}) +res = dk.containers:list({query = {all=true}}) if res.code <300 then containers = res.body else return end function get_volumes() @@ -50,7 +50,7 @@ local volume_list = get_volumes() -- m = Map("docker", translate("Docker")) m = SimpleForm("docker", translate("Docker")) -m.template = "docker/cbi/xsimpleform" +m.template = "dockerman/cbi/xsimpleform" m.submit=false m.reset=false @@ -72,7 +72,7 @@ volume_selecter.write = function(self, section, value) end docker_status = m:section(SimpleSection) -docker_status.template="docker/apply_widget" +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 @@ -82,7 +82,7 @@ action.rowcolors=false action.template="cbi/nullsection" btnremove = action:option(Button, "remove") btnremove.inputtitle= translate("Remove") -btnremove.template="docker/cbi/inlinebutton" +btnremove.template = "dockerman/cbi/inlinebutton" btnremove.inputstyle = "remove" btnremove.forcewrite = true btnremove.write = function(self, section) @@ -101,7 +101,7 @@ btnremove.write = function(self, section) docker:clear_status() for _,vol in ipairs(volume_selected) do docker:append_status("Volumes: " .. "remove" .. " " .. vol .. "...") - local msg = dk.volumes["remove"](dk, 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 diff --git a/package/lean/luci-app-dockerman/luasrc/model/docker.lua b/package/lean/luci-app-dockerman/luasrc/model/docker.lua index e61d8f95a..3374752e6 100644 --- a/package/lean/luci-app-dockerman/luasrc/model/docker.lua +++ b/package/lean/luci-app-dockerman/luasrc/model/docker.lua @@ -13,16 +13,16 @@ local _docker = {} local update_image = function(self, image_name) local server = "index.docker.io" - local json_stringify = luci.json and luci.json.encode or luci.jsonc.stringify + 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(nil, {fromImage=image_name, _header={["X-Registry-Auth"]=x_auth}}) + 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(image_name).body.Id + new_image_id = self.images:inspect({name = image_name}).body.Id return new_image_id, res end @@ -126,10 +126,10 @@ local get_config = function(old_config, old_host_config, old_network_setting, im return create_body, extra_network end -local upgrade = function(self, container_id) +local upgrade = function(self, request) _docker:clear_status() -- get image name, image id, container name, configuration information - local container_info = self.containers:inspect(container_id) + 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 @@ -148,7 +148,7 @@ local upgrade = function(self, container_id) end _docker:append_status("Container: " .. "Stop" .. " " .. container_name .. "...") - res = self.containers:stop(container_name) + res = self.containers:stop({name = container_name}) if res and res.code < 305 then _docker:append_status("done
") else @@ -156,7 +156,7 @@ local upgrade = function(self, container_id) end _docker:append_status("Container: rename" .. " " .. container_name .. " to ".. container_name .. "_old ...") - res = self.containers:rename(container_name,{ name = 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 @@ -164,12 +164,12 @@ local upgrade = function(self, container_id) end -- handle config - local image_config = self.images:inspect(old_image_id).body.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(container_name, nil, create_body) + res = self.containers:create({name = container_name, body = create_body}) if res and res.code > 300 then return res end _docker:append_status("done
") @@ -180,7 +180,7 @@ local upgrade = function(self, container_id) if v.Aliases and next(v.Aliases) == nil then v.Aliases =nil end _docker:append_status("Networks: Connect" .. " " .. container_name .. "...") - res = self.networks:connect(k, nil, {Container = container_name, EndpointConfig = v}) + res = self.networks:connect({id = k, body = {Container = container_name, EndpointConfig = v}}) if res.code > 300 then return res end _docker:append_status("done
") @@ -189,32 +189,32 @@ local upgrade = function(self, container_id) return res end -local duplicate_config = function (self, container_id) - local container_info = self.containers:inspect(container_id) +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(old_image_id).body.Config + 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("docker", "local", "socket_path"), - debug = option.debug or uci:get("docker", "local", "debug") == 'true' and true or false, - debug_path = option.debug_path or uci:get("docker", "local", "debug_path") + 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("docker", "local", "status_path") + _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("docker", "local", "status_path") +_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+") diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/apply_widget.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/apply_widget.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/cbi/dummyvalue.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/dummyvalue.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/cbi/dummyvalue.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/dummyvalue.htm diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/cbi/inlinebutton.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinebutton.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/cbi/inlinebutton.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinebutton.htm diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/cbi/inlinevalue.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/cbi/inlinevalue.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/cbi/xdynlist.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xdynlist.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/cbi/xdynlist.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xdynlist.htm diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/cbi/xfvalue.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xfvalue.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/cbi/xfvalue.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xfvalue.htm diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/cbi/xsimpleform.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm similarity index 98% rename from package/lean/luci-app-dockerman/luasrc/view/docker/cbi/xsimpleform.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm index 7cfe8bf21..24975fe11 100644 --- a/package/lean/luci-app-dockerman/luasrc/view/docker/cbi/xsimpleform.htm +++ b/package/lean/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm @@ -8,7 +8,7 @@ }, path = { resource = resource, - browser = url("admin/filebrowser") + browser = url("admin/services/filebrowser") } })) %>> diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/container.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/container.htm similarity index 87% rename from package/lean/luci-app-dockerman/luasrc/view/docker/container.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/container.htm index da53b75e5..70e552444 100644 --- a/package/lean/luci-app-dockerman/luasrc/view/docker/container.htm +++ b/package/lean/luci-app-dockerman/luasrc/view/dockerman/container.htm @@ -3,6 +3,7 @@
  • <%:Info%>
  • <%:Edit%>
  • <%:Stats%>
  • +
  • <%:File%>
  • <%:Logs%>
  • @@ -12,7 +13,7 @@ let path = p.split(re) let container_id = path[1].split('/')[0] || path[1] let action = path[1].split('/')[1] || "info" - let actions=["info","edit","stats","logs"] + let actions=["info","edit","stats","file","logs"] actions.forEach(function(item) { document.getElementById("a-cbi-tab-container_" + item).href= path[0]+"/admin/services/docker/container/"+container_id+'/'+item if (action === item) { 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 new file mode 100644 index 000000000..07e6c7374 --- /dev/null +++ b/package/lean/luci-app-dockerman/luasrc/view/dockerman/container_file.htm @@ -0,0 +1,54 @@ + +
    + +
    + +
    +
    + +
    + +
    +
    +
    + + +
    +
    + diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/logs.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/logs.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/logs.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/logs.htm diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/overview.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/overview.htm similarity index 99% rename from package/lean/luci-app-dockerman/luasrc/view/docker/overview.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/overview.htm index f8b67eee3..e9b443149 100644 --- a/package/lean/luci-app-dockerman/luasrc/view/docker/overview.htm +++ b/package/lean/luci-app-dockerman/luasrc/view/dockerman/overview.htm @@ -162,8 +162,8 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md

    <%:Images%>

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

    diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/resolv_container.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/resolv_container.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/resolv_container.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/resolv_container.htm diff --git a/package/lean/luci-app-dockerman/luasrc/view/docker/stats.htm b/package/lean/luci-app-dockerman/luasrc/view/dockerman/stats.htm similarity index 100% rename from package/lean/luci-app-dockerman/luasrc/view/docker/stats.htm rename to package/lean/luci-app-dockerman/luasrc/view/dockerman/stats.htm diff --git a/package/lean/luci-app-dockerman/po/zh-cn/dockerman.po b/package/lean/luci-app-dockerman/po/zh-cn/dockerman.po index 083a38bdf..0030f17bb 100644 --- a/package/lean/luci-app-dockerman/po/zh-cn/dockerman.po +++ b/package/lean/luci-app-dockerman/po/zh-cn/dockerman.po @@ -253,8 +253,8 @@ msgstr "保存docker status文件的位置" msgid "Enable Debug" msgstr "启用调试" -msgid "For debug, It shows all docker API actions of luci-app-dockermab in Debug Tempfile Path" -msgstr "用于调试,它在调试临时文件路径中显示 luci-app-dockermab 的所有docker API操作" +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 "调试临时文件路径" @@ -328,5 +328,26 @@ msgstr "结束时间" msgid "Command line Error" msgstr "命令行错误" -msgid "Canceled" -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/docker b/package/lean/luci-app-dockerman/root/etc/config/dockerman similarity index 100% rename from package/lean/luci-app-dockerman/root/etc/config/docker rename to package/lean/luci-app-dockerman/root/etc/config/dockerman diff --git a/package/lean/luci-lib-docker/Makefile b/package/lean/luci-lib-docker/Makefile index f8ff83eb9..a9a88b92f 100644 --- a/package/lean/luci-lib-docker/Makefile +++ b/package/lean/luci-lib-docker/Makefile @@ -1,16 +1,18 @@ -# -# Copyright (C) 2019 lisaac -# -# This is free software, licensed under the Apache License, Version 2.0 . -# include $(TOPDIR)/rules.mk PKG_NAME:=luci-lib-docker -PKG_VERSION:=v0.1.1 +PKG_VERSION:=v0.3.0 PKG_RELEASE:=beta PKG_MAINTAINER:=lisaac -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) -PKG_LICENSE:=Apache-2.0 +PKG_LICENSE:=AGPL-3.0 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/lisaac/luci-lib-docker.git +PKG_SOURCE_VERSION:=$(PKG_VERSION) + +PKG_SOURCE_SUBDIR:=$(PKG_NAME) +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR)-$(PKG_VERSION).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) include $(INCLUDE_DIR)/package.mk @@ -28,6 +30,7 @@ define Package/$(PKG_NAME)/description endef define Build/Prepare + tar -xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(BUILD_DIR) endef define Build/Compile @@ -40,7 +43,7 @@ endef define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/usr/lib/lua/luci - cp -pR ./luasrc/* $(1)/usr/lib/lua/luci + cp -pR $(PKG_BUILD_DIR)/luasrc/* $(1)/usr/lib/lua/luci/ endef $(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lean/luci-lib-docker/luasrc/docker.lua b/package/lean/luci-lib-docker/luasrc/docker.lua index 0d7e27f14..8a5f056fc 100644 --- a/package/lean/luci-lib-docker/luasrc/docker.lua +++ b/package/lean/luci-lib-docker/luasrc/docker.lua @@ -1,13 +1,13 @@ require "nixio.util" require "luci.util" - local json = require "luci.json" +local jsonc = require "luci.jsonc" local nixio = require "nixio" local ltn12 = require "luci.ltn12" local fs = require "nixio.fs" local urlencode = luci.util.urlencode or luci.http and luci.http.protocol and luci.http.protocol.urlencode -local json_stringify = json.encode --luci.json and luci.json.encode or luci.jsonc.stringify -local json_parse = json.decode --luci.json and luci.json.decode or luci.jsonc.parse +local json_stringify = jsonc.stringify +local json_parse = jsonc.parse local chunksource = function(sock, buffer) buffer = buffer or "" @@ -58,6 +58,16 @@ local chunksource = function(sock, buffer) end end +local chunksink = function (sock) + return function(chunk, err) + if not chunk then + return sock:writeall("0\r\n\r\n") + else + return sock:writeall(("%X\r\n%s\r\n"):format(#chunk, tostring(chunk))) + end + end +end + local docker_stream_filter = function(buffer) buffer = buffer or "" if #buffer < 8 then @@ -73,80 +83,44 @@ local docker_stream_filter = function(buffer) -- return string.sub(buffer, 9, valid_length + 8) end -local gen_http_req = function(options) - local req - options = options or {} - options.protocol = options.protocol or "HTTP/1.1" - req = (options.method or "GET") .. " " .. options.path .. " " .. options.protocol .. "\r\n" - req = req .. "Host: " .. options.host .. "\r\n" - req = req .. "User-Agent: " .. options.user_agent .. "\r\n" - req = req .. "Connection: close\r\n" - if type(options.header) == "table" then - for k, v in pairs(options.header) do - req = req .. k .. ": " .. v .."\r\n" - end - end - if options.method == "POST" and type(options.conetnt) == "table" then - local conetnt_json = json_stringify(options.conetnt) - req = req .. "Content-Type: application/json\r\n" - req = req .. "Content-Length: " .. #conetnt_json .. "\r\n" - req = req .. "\r\n" .. conetnt_json - elseif options.method == "PUT" and options.conetnt then - req = req .. "Content-Type: application/x-tar\r\n" - req = req .. "Content-Length: " .. #options.conetnt .. "\r\n" - req = req .. "\r\n" .. options.conetnt - else - req = req .. "\r\n" - end - if options.debug then io.popen("echo '".. req .. "' >> " .. options.debug_path) end - return req -end - -local send_http_socket = function(socket_path, req) +local send_http_socket = function(socket_path, req_header, req_body, callback) local docker_socket = nixio.socket("unix", "stream") if docker_socket:connect(socket_path) ~= true then return { - headers={ - code=497, - message="bad socket path", - protocol="HTTP/1.1" - }, - body={ - message="can\'t connect to unix socket" - } + headers = {code=497, message="bad socket path", protocol="HTTP/1.1"}, + body = {message="can\'t connect to unix socket"} } end - if docker_socket:send(req) == 0 then + if docker_socket:send(req_header) == 0 then return { - headers={ - code=498, - message="bad socket path", - protocol="HTTP/1.1" - }, - body={ - message="can\'t send data to unix socket" - } + headers={code=498,message="bad socket path", protocol="HTTP/1.1"}, + body={message="can\'t send data to unix socket"} } end - -- local data, err_code, err_msg, data_f = docker_socket:readall() - -- docker_socket:close() + + if req_body and type(req_body) == "function" and req_header and req_header:match("chunked") then + -- chunked send + req_body(chunksink(docker_socket)) + elseif req_body and type(req_body) == "function" then + -- normal send by req_body function + req_body(docker_socket) + elseif req_body and type(req_body) == "table" then + -- json + docker_socket:send(json_stringify(req_body)) + elseif req_body then + docker_socket:send(req_body) + end + local linesrc = docker_socket:linesource() -- read socket using source http://w3.impa.br/~diego/software/luasocket/ltn12.html --http://lua-users.org/wiki/FiltersSourcesAndSinks - -- handle response header local line = linesrc() if not line then docker_socket:close() return { - headers={ - code=499, - message="bad socket path", - protocol="HTTP/1.1" - }, - body={ - message="no data receive from socket" - } + headers = {code=499, message="bad socket path", protocol="HTTP/1.1"}, + body = {message="no data receive from socket"} } end local response = {code = 0, headers = {}, body = {}} @@ -172,64 +146,85 @@ local send_http_socket = function(socket_path, req) -- handle response body local body_buffer = linesrc(true) response.body = {} - if response.headers["Transfer-Encoding"] == "chunked" then - local source = chunksource(docker_socket, body_buffer) - code = ltn12.pump.all(source, (ltn12.sink.table(response.body))) and response.code or 555 - response.code = code + if type(callback) ~= "function" then + if response.headers["Transfer-Encoding"] == "chunked" then + local source = chunksource(docker_socket, body_buffer) + code = ltn12.pump.all(source, (ltn12.sink.table(response.body))) and response.code or 555 + response.code = code + else + local body_source = ltn12.source.cat(ltn12.source.string(body_buffer), docker_socket:blocksource()) + code = ltn12.pump.all(body_source, (ltn12.sink.table(response.body))) and response.code or 555 + response.code = code + end else - local body_source = ltn12.source.cat(ltn12.source.string(body_buffer), docker_socket:blocksource()) - code = ltn12.pump.all(body_source, (ltn12.sink.table(response.body))) and response.code or 555 - response.code = code + if response.headers["Transfer-Encoding"] == "chunked" then + local source = chunksource(docker_socket, body_buffer) + callback(response, source) + else + local body_source = ltn12.source.cat(ltn12.source.string(body_buffer), docker_socket:blocksource()) + callback(response, body_source) + end end docker_socket:close() return response end -local send_http_require = function(options, method, api_group, api_action, name_or_id, request_qurey, request_body) - local qurey - local req_options = setmetatable({}, {__index = options}) +local gen_header = function(options, http_method, api_group, api_action, name_or_id, request) + local header, query, path + options = options or {} + options.protocol = options.protocol or "HTTP/1.1" + name_or_id = name_or_id ~= "" and name_or_id or nil - -- for docker action status - -- if options.status_enabled then - -- fs.writefile(options.status_path, api_group or "" .. " " .. api_action or "" .. " " .. name_or_id or "") - -- end - - -- request_qurey = request_qurey or {} - -- request_body = request_body or {} - if name_or_id == "" then - name_or_id = nil - end - req_options.method = method - req_options.path = (api_group and ("/" .. api_group) or "") .. (name_or_id and ("/" .. name_or_id) or "") .. (api_action and ("/" .. api_action) or "") - req_options.header = {} - if type(request_qurey) == "table" then - for k, v in pairs(request_qurey) do + if request and type(request.query) == "table" then + local k, v + for k, v in pairs(request.query) do if type(v) == "table" then - if k ~= "_header" then - qurey = (qurey and qurey .. "&" or "?") .. k .. "=" .. urlencode(json_stringify(v)) - else - -- for http header - for k1, v1 in pairs(v) do - req_options.header[k1] = v1 - end - end + query = (query and query .. "&" or "?") .. k .. "=" .. urlencode(json_stringify(v)) elseif type(v) == "boolean" then - qurey = (qurey and qurey .. "&" or "?") .. k .. "=" .. (v and "true" or "false") + query = (query and query .. "&" or "?") .. k .. "=" .. (v and "true" or "false") elseif type(v) == "number" or type(v) == "string" then - qurey = (qurey and qurey .. "&" or "?") .. k .. "=" .. v + query = (query and query .. "&" or "?") .. k .. "=" .. v end end end - req_options.path = req_options.path .. (qurey or "") - -- if type(request_body) == "table" then - req_options.conetnt = request_body - -- end - local response = send_http_socket(req_options.socket_path, gen_http_req(req_options)) - -- for docker action status - -- if options.status_enabled then - -- fs.remove(options.status_path) - -- end - return response + + path = (api_group and ("/" .. api_group) or "") .. (name_or_id and ("/" .. name_or_id) or "") .. (api_action and ("/" .. api_action) or "") .. (query or "") + header = (http_method or "GET") .. " " .. path .. " " .. options.protocol .. "\r\n" + header = header .. "Host: " .. options.host .. "\r\n" + header = header .. "User-Agent: " .. options.user_agent .. "\r\n" + header = header .. "Connection: close\r\n" + + if request and type(request.header) == "table" then + local k, v + for k, v in pairs(request.header) do + header = header .. k .. ": " .. v .. "\r\n" + end + end + + -- when requst_body is function, we need to custom header using custom header + if request and request.body and type(request.body) == "function" then + if not header:match("Content-Length:") then + header = header .. "Transfer-Encoding: chunked\r\n" + end + elseif http_method == "POST" and request and request.body and type(request.body) == "table" then + local conetnt_json = json_stringify(request.body) + header = header .. "Content-Type: application/json\r\n" + header = header .. "Content-Length: " .. #conetnt_json .. "\r\n" + elseif request and request.body and type(request.body) == "string" then + header = header .. "Content-Length: " .. #request.body .. "\r\n" + end + header = header .. "\r\n" + if options.debug then io.popen("echo '".. header .. "' >> " .. options.debug_path) end + return header +end + +local call_docker = function(options, http_method, api_group, api_action, name_or_id, request, callback) + local req_options = setmetatable({}, {__index = options}) + + local req_header = gen_header(req_options, http_method, api_group, api_action, name_or_id, request) + local req_body = request and request.body or nil + + return send_http_socket(req_options.socket_path, req_header, req_body, callback) end local gen_api = function(_table, http_method, api_group, api_action) @@ -244,28 +239,29 @@ local gen_api = function(_table, http_method, api_group, api_action) _api_action = "json" end - local fp = function(self, name_or_id, request_qurey, request_body) + local fp = function(self, request, callback) + local name_or_id = request and (request.name or request.id or request.name_or_id) or nil if api_action == "list" then if (name_or_id ~= "" and name_or_id ~= nil) then if api_group == "images" then name_or_id = nil else - request_qurey = request_qurey or {} - request_qurey.filters = request_qurey.filters or {} - request_qurey.filters.name = request_qurey.filters.name or {} - request_qurey.filters.name[#request_qurey.filters.name + 1] = name_or_id + request.query = request and request.query or {} + request.query.filters = request.query.filters or {} + request.query.filters.name = request.query.filters.name or {} + request.query.filters.name[#request.query.filters.name + 1] = name_or_id name_or_id = nil end end elseif api_action == "create" then if (name_or_id ~= "" and name_or_id ~= nil) then - request_qurey = request_qurey or {} - request_qurey.name = request_qurey.name or name_or_id + request.query = request and request.query or {} + request.query.name = request.query.name or name_or_id name_or_id = nil end elseif api_action == "logs" then local body_buffer = "" - local response = send_http_require(self.options, http_method, api_group, _api_action, name_or_id, request_qurey, request_body) + local response = call_docker(self.options, http_method, api_group, _api_action, name_or_id, request, callback) if response.code >= 200 and response.code < 300 then for i, v in ipairs(response.body) do body_buffer = body_buffer .. docker_stream_filter(response.body[i]) @@ -274,7 +270,7 @@ local gen_api = function(_table, http_method, api_group, api_action) end return response end - local response = send_http_require(self.options, http_method, api_group, _api_action, name_or_id, request_qurey, request_body) + local response = call_docker(self.options, http_method, api_group, _api_action, name_or_id, request, callback) if response.headers and response.headers["Content-Type"] == "application/json" then if #response.body == 1 then response.body = json_parse(response.body[1])