From 28992ba6152278090f3aa56e4dd9d5c2ff5ce652 Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Sun, 22 Mar 2020 23:57:46 +0800 Subject: [PATCH] luci-app-dockerman: sync with upstream source --- package/ctcgfw/luci-app-dockerman/Makefile | 75 +++++++++++- package/ctcgfw/luci-app-dockerman/depends.lst | 1 + .../luasrc/controller/dockerman.lua | 106 ++++++++--------- .../luasrc/model/cbi/dockerman/container.lua | 36 +++--- .../luasrc/model/cbi/dockerman/containers.lua | 9 +- .../luasrc/model/cbi/dockerman/images.lua | 17 ++- .../luasrc/model/cbi/dockerman/networks.lua | 16 ++- .../model/cbi/dockerman/newcontainer.lua | 95 ++++++++++----- .../luasrc/model/cbi/dockerman/newnetwork.lua | 39 ++++--- .../luasrc/model/cbi/dockerman/overview.lua | 85 +++++++------- .../luasrc/model/cbi/dockerman/volumes.lua | 7 +- .../luasrc/model/docker.lua | 110 ++++++++++++++---- .../luasrc/view/dockerman/apply_widget.htm | 10 +- .../luasrc/view/dockerman/cbi/xdynlist.htm | 27 ----- .../luasrc/view/dockerman/cbi/xsimpleform.htm | 89 -------------- .../luasrc/view/dockerman/container.htm | 8 +- .../view/dockerman/container_console.htm | 2 +- .../luasrc/view/dockerman/container_file.htm | 6 +- .../luasrc/view/dockerman/container_stats.htm | 4 +- .../luasrc/view/dockerman/images_import.htm | 12 +- .../luasrc/view/dockerman/images_load.htm | 2 +- .../luasrc/view/dockerman/logs.htm | 2 +- .../view/dockerman/newcontainer_resolve.htm | 4 +- .../luasrc/view/dockerman/overview.htm | 10 +- .../luasrc/view/dockerman/overview_tab.htm | 31 ----- .../po/zh_Hans/dockerman.po | 30 +++++ .../root/etc/config/dockerd | 5 - .../root/etc/config/dockerman | 7 +- .../luci-app-dockerman/root/etc/docker-init | 25 ---- .../root/etc/init.d/dockerd | 66 ----------- .../root/etc/init.d/dockerman | 45 +++++++ .../root/etc/uci-defaults/luci-app-dockerman | 12 +- .../root/usr/share/dockerman/dockerd-ac.lua | 20 ++++ .../usr/share/dockerman/dockerd-config.lua | 50 ++++++++ 34 files changed, 574 insertions(+), 489 deletions(-) create mode 100644 package/ctcgfw/luci-app-dockerman/depends.lst delete mode 100644 package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/cbi/xdynlist.htm delete mode 100644 package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm delete mode 100644 package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/overview_tab.htm delete mode 100644 package/ctcgfw/luci-app-dockerman/root/etc/config/dockerd delete mode 100755 package/ctcgfw/luci-app-dockerman/root/etc/docker-init delete mode 100755 package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerd create mode 100755 package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerman create mode 100644 package/ctcgfw/luci-app-dockerman/root/usr/share/dockerman/dockerd-ac.lua create mode 100644 package/ctcgfw/luci-app-dockerman/root/usr/share/dockerman/dockerd-config.lua diff --git a/package/ctcgfw/luci-app-dockerman/Makefile b/package/ctcgfw/luci-app-dockerman/Makefile index 5839a7388b..79c96ec705 100644 --- a/package/ctcgfw/luci-app-dockerman/Makefile +++ b/package/ctcgfw/luci-app-dockerman/Makefile @@ -1,13 +1,76 @@ include $(TOPDIR)/rules.mk -LUCI_TITLE:=Docker Manager interface for LuCI -LUCI_DEPENDS:=+luci-lib-docker +docker-ce +e2fsprogs +fdisk +ttyd PKG_NAME:=luci-app-dockerman -PKG_VERSION:=v0.4.7 -PKG_RELEASE:=leanmod +PKG_VERSION:=v0.5.4 +PKG_RELEASE:=beta PKG_MAINTAINER:=lisaac PKG_LICENSE:=AGPL-3.0 -include $(TOPDIR)/feeds/luci/luci.mk +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/lisaac/luci-app-dockerman.git +PKG_SOURCE_VERSION:=$(PKG_VERSION) -# call BuildPackage - OpenWrt buildroot signature +PKG_SOURCE_SUBDIR:=$(PKG_NAME) +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR)-$(PKG_SOURCE_VERSION).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME)/config +config PACKAGE_$(PKG_NAME)_INCLUDE_docker_ce + bool "Include Docker-CE" + default n +config PACKAGE_$(PKG_NAME)_INCLUDE_ttyd + bool "Include ttyd" + default y +endef + +define Package/$(PKG_NAME) + SECTION:=luci + CATEGORY:=LuCI + SUBMENU:=3. Applications + TITLE:=Docker Manager interface for LuCI + PKGARCH:=all + DEPENDS:=+luci-lib-docker \ + +PACKAGE_$(PKG_NAME)_INCLUDE_docker_ce:docker-ce \ + +PACKAGE_$(PKG_NAME)_INCLUDE_ttyd:ttyd +endef + +define Package/$(PKG_NAME)/description + Docker Manager interface for LuCI +endef + +define Build/Prepare + tar -xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(BUILD_DIR) +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/postinst +#!/bin/sh +if [ -z "$${IPKG_INSTROOT}" ]; then + ( . /etc/uci-defaults/luci-app-dockerman ) && rm -f /etc/uci-defaults/luci-app-dockerman +fi +exit 0 +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/etc/config + cp -pR $(PKG_BUILD_DIR)/root/etc/config/* $(1)/etc/config/ + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) $(PKG_BUILD_DIR)/root/etc/init.d/* $(1)/etc/init.d/ + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) $(PKG_BUILD_DIR)/root/etc/uci-defaults/* $(1)/etc/uci-defaults/ + # $(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 + $$(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_Hans/dockerman.po $(1)/usr/lib/lua/luci/i18n/dockerman.zh-cn.lmo +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/ctcgfw/luci-app-dockerman/depends.lst b/package/ctcgfw/luci-app-dockerman/depends.lst new file mode 100644 index 0000000000..5cf6cf03f0 --- /dev/null +++ b/package/ctcgfw/luci-app-dockerman/depends.lst @@ -0,0 +1 @@ +ttyd \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/controller/dockerman.lua b/package/ctcgfw/luci-app-dockerman/luasrc/controller/dockerman.lua index 12f37bee6a..719be77734 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/controller/dockerman.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/controller/dockerman.lua @@ -10,8 +10,8 @@ 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 + entry({"admin", "docker"}, firstchild(), "Docker", 40).dependent = false + entry({"admin","docker","overview"},cbi("dockerman/overview"),_("Overview"),0).leaf=true local remote = luci.model.uci.cursor():get("dockerman", "local", "remote_endpoint") if remote == nil then @@ -24,24 +24,24 @@ function index() 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","images_save"},call("save_images")).leaf=true - entry({"admin","services","docker","images_load"},call("load_images")).leaf=true - entry({"admin","services","docker","images_import"},call("import_images")).leaf=true - entry({"admin","services","docker","images_get_tags"},call("get_image_tags")).leaf=true - entry({"admin","services","docker","images_tag"},call("tag_image")).leaf=true - entry({"admin","services","docker","images_untag"},call("untag_image")).leaf=true - entry({"admin","services","docker","confirm"},call("action_confirm")).leaf=true + entry({"admin","docker","containers"},form("dockerman/containers"),_("Containers"),1).leaf=true + entry({"admin","docker","images"},form("dockerman/images"),_("Images"),2).leaf=true + entry({"admin","docker","networks"},form("dockerman/networks"),_("Networks"),3).leaf=true + entry({"admin","docker","volumes"},form("dockerman/volumes"),_("Volumes"),4).leaf=true + entry({"admin","docker","events"},call("action_events"),_("Events"),5) + entry({"admin","docker","newcontainer"},form("dockerman/newcontainer")).leaf=true + entry({"admin","docker","newnetwork"},form("dockerman/newnetwork")).leaf=true + entry({"admin","docker","container"},form("dockerman/container")).leaf=true + entry({"admin","docker","container_stats"},call("action_get_container_stats")).leaf=true + entry({"admin","docker","container_get_archive"},call("download_archive")).leaf=true + entry({"admin","docker","container_put_archive"},call("upload_archive")).leaf=true + entry({"admin","docker","images_save"},call("save_images")).leaf=true + entry({"admin","docker","images_load"},call("load_images")).leaf=true + entry({"admin","docker","images_import"},call("import_images")).leaf=true + entry({"admin","docker","images_get_tags"},call("get_image_tags")).leaf=true + entry({"admin","docker","images_tag"},call("tag_image")).leaf=true + entry({"admin","docker","images_untag"},call("untag_image")).leaf=true + entry({"admin","docker","confirm"},call("action_confirm")).leaf=true end function action_events() @@ -272,39 +272,39 @@ function load_images() luci.http.write_json({message = msg}) end --- function import_images() --- local src = luci.http.formvalue("src") --- local itag = luci.http.formvalue("tag") --- local dk = docker.new() --- local ltn12 = require "luci.ltn12" --- local 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 --- docker:write_status("Images: importing".. " ".. itag .."...\n") --- local repo = itag and itag:match("^([^:]+)") --- local tag = itag and itag:match("^[^:]-:([^:]+)") --- local res = dk.images:create({query = {fromSrc = src or "-", repo = repo or nil, tag = tag or nil }, body = not src and rec_send or nil}, docker.import_image_show_status_cb) --- local msg = res and res.body and ( res.body.message )or nil --- if not msg and #res.body == 0 then --- -- res.body = {"status":"sha256:d5304b58e2d8cc0a2fd640c05cec1bd4d1229a604ac0dd2909f13b2b47a29285"} --- msg = res.body.status or res.body.error --- elseif not msg and #res.body >= 1 then --- -- res.body = [...{"status":"sha256:d5304b58e2d8cc0a2fd640c05cec1bd4d1229a604ac0dd2909f13b2b47a29285"}] --- msg = res.body[#res.body].status or res.body[#res.body].error --- end --- if res.code == 200 and msg and msg:match("sha256:") then --- docker:clear_status() --- else --- docker:append_status("code:" .. res.code.." ".. msg) --- end --- luci.http.status(res.code, msg) --- luci.http.prepare_content("application/json") --- luci.http.write_json({message = msg}) --- end +function import_images() + local src = luci.http.formvalue("src") + local itag = luci.http.formvalue("tag") + local dk = docker.new() + local ltn12 = require "luci.ltn12" + local 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 + docker:write_status("Images: importing".. " ".. itag .."...\n") + local repo = itag and itag:match("^([^:]+)") + local tag = itag and itag:match("^[^:]-:([^:]+)") + local res = dk.images:create({query = {fromSrc = src or "-", repo = repo or nil, tag = tag or nil }, body = not src and rec_send or nil}, docker.import_image_show_status_cb) + local msg = res and res.body and ( res.body.message )or nil + if not msg and #res.body == 0 then + -- res.body = {"status":"sha256:d5304b58e2d8cc0a2fd640c05cec1bd4d1229a604ac0dd2909f13b2b47a29285"} + msg = res.body.status or res.body.error + elseif not msg and #res.body >= 1 then + -- res.body = [...{"status":"sha256:d5304b58e2d8cc0a2fd640c05cec1bd4d1229a604ac0dd2909f13b2b47a29285"}] + msg = res.body[#res.body].status or res.body[#res.body].error + end + if res.code == 200 and msg and msg:match("sha256:") then + docker:clear_status() + else + docker:append_status("code:" .. res.code.." ".. msg) + end + luci.http.status(res.code, msg) + luci.http.prepare_content("application/json") + luci.http.write_json({message = msg}) +end function get_image_tags(image_id) if not image_id then diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua index 2463e87254..598e1e33b7 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua @@ -4,7 +4,6 @@ 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] @@ -146,20 +145,19 @@ local start_stop_remove = function(m, cmd) end if res and res.code >= 300 then docker:append_status("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)) + luci.http.redirect(luci.dispatcher.build_url("admin/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)) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/container/"..container_id)) else - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/containers")) + luci.http.redirect(luci.dispatcher.build_url("admin/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.redirect = luci.dispatcher.build_url("admin/docker/containers") -- m:append(Template("dockerman/container")) docker_status = m:section(SimpleSection) docker_status.template = "dockerman/apply_widget" @@ -220,7 +218,7 @@ 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)) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer/duplicate/"..container_id)) end tab_section = m:section(SimpleSection) @@ -305,7 +303,9 @@ if action == "info" then self:reset_values() self.size = nil for k,v in pairs(list_networks) do - self:value(k,v) + if k ~= "host" then + self:value(k,v) + end end self.default=table_info[section]._value ListValue.render(self, section, scope) @@ -364,7 +364,6 @@ if action == "info" then end end btn_update.write = function(self, section, value) - -- luci.util.perror(section) local res docker:clear_status() if section == "01name" then @@ -384,7 +383,6 @@ if action == "info" 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 @@ -399,7 +397,7 @@ if action == "info" then else docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/container/"..container_id.."/info")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/container/"..container_id.."/info")) end -- info end @@ -459,7 +457,7 @@ elseif action == "edit" then else docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/container/"..container_id.."/edit")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/container/"..container_id.."/edit")) end end elseif action == "file" then @@ -491,7 +489,7 @@ elseif action == "console" then m.reset = false local cmd_docker = luci.util.exec("which docker"):match("^.+docker") or nil local cmd_ttyd = luci.util.exec("which ttyd"):match("^.+ttyd") or nil - if cmd_docker and cmd_ttyd then + if cmd_docker and cmd_ttyd and container_info.State.Status == "running" then local consolesection= m:section(SimpleSection) local cmd = "/bin/sh" local uid @@ -521,9 +519,11 @@ elseif action == "console" then local cmd_ttyd = luci.util.exec("which ttyd"):match("^.+ttyd") or nil if not cmd_docker or not cmd_ttyd or cmd_docker:match("^%s+$") or cmd_ttyd:match("^%s+$") then return end local kill_ttyd = 'netstat -lnpt | grep ":7682[ \t].*ttyd$" | awk \'{print $NF}\' | awk -F\'/\' \'{print "kill -9 " $1}\' | sh > /dev/null' + luci.util.exec(kill_ttyd) local hosts + local uci = (require "luci.model.uci").cursor() local remote = uci:get("dockerman", "local", "remote_endpoint") - local socket_path = (remote == "false") and uci:get("dockerman", "local", "socket_path") or nil + local socket_path = (remote == "false" or not remote) and uci:get("dockerman", "local", "socket_path") or nil local host = (remote == "true") and uci:get("dockerman", "local", "remote_host") or nil local port = (remote == "true") and uci:get("dockerman", "local", "remote_port") or nil if remote and host and port then @@ -533,9 +533,8 @@ elseif action == "console" then else return end - - local start_cmd = cmd_ttyd .. ' -d 2 -p 7682 '.. cmd_docker .. ' -H "'.. hosts ..'" exec -it ' .. (uid and uid ~= "" and (" -u ".. uid .. ' ') or "").. container_id .. ' ' .. cmd .. ' &' - local res = luci.util.exec(start_cmd) + local start_cmd = cmd_ttyd .. ' -d 2 --once -p 7682 '.. cmd_docker .. ' -H "'.. hosts ..'" exec -it ' .. (uid and uid ~= "" and (" -u ".. uid .. ' ') or "").. container_id .. ' ' .. cmd .. ' &' + os.execute(start_cmd) local console = consolesection:option(DummyValue, "console") console.container_id = container_id console.template = "dockerman/container_console" @@ -561,7 +560,6 @@ elseif action == "stats" then 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 @@ -572,4 +570,4 @@ m.submit = false m.reset = false end -return m +return m \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua index 3520a8a3e7..74b9872b1d 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua @@ -28,7 +28,7 @@ function get_containers() data[index]["_selected"] = 0 data[index]["_id"] = v.Id:sub(1,12) data[index]["name"] = v.Names[1]:sub(2) - data[index]["_name"] = ''.. v.Names[1]:sub(2).."" + data[index]["_name"] = ''.. v.Names[1]:sub(2).."" data[index]["_status"] = v.Status if v.Status:find("^Up") then data[index]["_status"] = ''.. data[index]["_status"] .. "" @@ -69,7 +69,6 @@ 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 @@ -132,7 +131,7 @@ local start_stop_remove = function(m,cmd) end end if success then docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/containers")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/containers")) end end @@ -167,7 +166,7 @@ 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")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer")) end btnstart.write = function(self, section) start_stop_remove(m,"start") @@ -182,4 +181,4 @@ btnstop.write = function(self, section) start_stop_remove(m,"stop") end -return m +return m \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua index 5c41b63b13..d16e73bfa5 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua @@ -38,7 +38,7 @@ function get_images() 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).."" + ''.. cv.Names[1]:sub(2).."" end end data[index]["_size"] = string.format("%.2f", tostring(v.Size/1024/1024)).."MB" @@ -51,7 +51,6 @@ 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 @@ -60,7 +59,7 @@ local pull_section = m:section(SimpleSection, 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" +tag_name.placeholder="lisaac/luci:latest" local action_pull = pull_section:option(Button, "_pull") action_pull.inputtitle= translate("Pull") action_pull.template = "dockerman/cbi/inlinebutton" @@ -88,12 +87,12 @@ action_pull.write = function(self, section) else docker:append_status("code: 400 please input the name of image name!") end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/images")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/images")) end --- local import_section = m:section(SimpleSection, translate("Import Images")) --- local im = import_section:option(DummyValue, "_image_import") --- im.template = "dockerman/images_import" +local import_section = m:section(SimpleSection, translate("Import Images")) +local im = import_section:option(DummyValue, "_image_import") +im.template = "dockerman/images_import" local image_table = m:section(Table, image_list, translate("Images")) @@ -138,7 +137,7 @@ local remove_action = function(force) end end if success then docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/images")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/images")) end end @@ -221,4 +220,4 @@ local btnload = action:option(Button, "load") btnload.inputtitle= translate("Load") btnload.template = "dockerman/images_load" btnload.inputstyle = "add" -return m +return m \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua index ec96756740..1659596a47 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua @@ -36,7 +36,6 @@ 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 @@ -84,7 +83,7 @@ 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")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newnetwork")) end btnremove = action:option(Button, "_remove") btnremove.inputtitle= translate("Remove") @@ -93,18 +92,22 @@ btnremove.inputstyle = "remove" btnremove.forcewrite = true btnremove.write = function(self, section) local network_selected = {} + local network_name_selected = {} + local network_driver_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_list[network_table_sid]._id --network_name:cfgvalue(network_table_sid) + network_name_selected[#network_name_selected+1] = network_list[network_table_sid]._name + network_driver_selected[#network_driver_selected+1] = network_list[network_table_sid]._driver end end if next(network_selected) ~= nil then local success = true docker:clear_status() - for _,net in ipairs(network_selected) do + for ii, 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 @@ -112,13 +115,16 @@ btnremove.write = function(self, section) success = false else docker:append_status("done\n") + if network_driver_selected[ii] == "macvlan" then + docker.remove_macvlan_interface(network_name_selected[ii]) + end end end if success then docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/networks")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/networks")) end end -return m +return m \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua index 30c9720f95..dcb19a2fb4 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua @@ -32,7 +32,7 @@ end local resolve_cli = function(cmd_line) local config = {advance = 1} - local key_no_val = '|t|d|i|tty|rm|read-only|interactive|init|help|detach|privileged|' + local key_no_val = '|t|d|i|tty|rm|read_only|interactive|init|help|detach|privileged|' local key_with_val = '|sysctl|add_host|a|attach|blkio_weight_device|cap_add|cap_drop|device|device_cgroup_rule|device_read_bps|device_read_iops|device_write_bps|device_write_iops|dns|dns_option|dns_search|e|env|env_file|expose|group_add|l|label|label_file|link|link_local_ip|log_driver|log_opt|network_alias|p|publish|security_opt|storage_opt|tmpfs|v|volume|volumes_from|blkio_weight|cgroup_parent|cidfile|cpu_period|cpu_quota|cpu_rt_period|cpu_rt_runtime|c|cpu_shares|cpus|cpuset_cpus|cpuset_mems|detach_keys|disable_content_trust|domainname|entrypoint|gpus|health_cmd|health_interval|health_retries|health_start_period|health_timeout|h|hostname|ip|ip6|ipc|isolation|kernel_memory|log_driver|mac_address|m|memory|memory_reservation|memory_swap|memory_swappiness|mount|name|network|no_healthcheck|oom_kill_disable|oom_score_adj|pid|pids_limit|P|publish_all|restart|runtime|shm_size|sig_proxy|stop_signal|stop_timeout|ulimit|u|user|userns|uts|volume_driver|w|workdir|' local key_abb = {net='network',a='attach',c='cpu-shares',d='detach',e='env',h='hostname',i='interactive',l='label',m='memory',p='publish',P='publish_all',t='tty',u='user',v='volume',w='workdir'} local key_with_list = '|sysctl|add_host|a|attach|blkio_weight_device|cap_add|cap_drop|device|device_cgroup_rule|device_read_bps|device_read_iops|device_write_bps|device_write_iops|dns|dns_option|dns_search|e|env|env_file|expose|group_add|l|label|label_file|link|link_local_ip|log_driver|log_opt|network_alias|p|publish|security_opt|storage_opt|tmpfs|v|volume|volumes_from|' @@ -55,7 +55,7 @@ local resolve_cli = function(cmd_line) key = w:match("^%-([%lP%-]+)") if key then -- for -dit - if key:match("i") or key:match("t") then + if key:match("i") or key:match("t") or key:match("d") then if key:match("i") then config[key_abb["i"]] = true key:gsub("i", "") @@ -75,14 +75,13 @@ local resolve_cli = function(cmd_line) end if key then key = key:gsub("-","_") + key = key_abb[key] or key if key_no_val:match("|"..key.."|") then - key = key_abb[key] or key config[key] = true val = nil key = nil elseif key_with_val:match("|"..key.."|") then - key = key_abb[key] or key - if key == "cap_add" then config.privileged = true end + -- if key == "cap_add" then config.privileged = true end else key = nil val = nil @@ -94,13 +93,39 @@ local resolve_cli = function(cmd_line) is_cmd = true end elseif (key or _key) and not is_cmd then - val = w + if key == "mount" then + -- we need resolve mount options here + -- type=bind,source=/source,target=/app + local _type = w:match("^type=([^,]+),") or "bind" + local source = (_type ~= "tmpfs") and (w:match("source=([^,]+),") or w:match("src=([^,]+),")) or "" + local target = w:match(",target=([^,]+)") or w:match(",dst=([^,]+)") or w:match(",destination=([^,]+)") or "" + local ro = w:match(",readonly") and "ro" or nil + if source and target then + if _type ~= "tmpfs" then + -- bind or volume + local bind_propagation = (_type == "bind") and w:match(",bind%-propagation=([^,]+)") or nil + val = source..":"..target .. ((ro or bind_propagation) and (":" .. (ro and ro or "") .. (((ro and bind_propagation) and "," or "") .. (bind_propagation and bind_propagation or ""))or "")) + else + -- tmpfs + local tmpfs_mode = w:match(",tmpfs%-mode=([^,]+)") or nil + local tmpfs_size = w:match(",tmpfs%-size=([^,]+)") or nil + key = "tmpfs" + val = target .. ((tmpfs_mode or tmpfs_size) and (":" .. (tmpfs_mode and ("mode=" .. tmpfs_mode) or "") .. ((tmpfs_mode and tmpfs_size) and "," or "") .. (tmpfs_size and ("size=".. tmpfs_size) or "")) or "") + if not config[key] then config[key] = {} end + table.insert( config[key], val ) + key = nil + val = nil + end + end + else + val = w + end elseif is_cmd then config["command"] = (config["command"] and (config["command"] .. " " )or "") .. w end if (key or _key) and val then key = _key or key - if key_with_list:match(key) then + if key_with_list:match("|"..key.."|") then if not config[key] then config[key] = {} end if _key then config[key][#config[key]] = config[key][#config[key]] .. " " .. w @@ -154,6 +179,7 @@ elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then default_config.env = create_body.Env default_config.dns = create_body.HostConfig.Dns default_config.volume = create_body.HostConfig.Binds + default_config.cap_add = create_body.HostConfig.CapAdd if create_body.HostConfig.Sysctls and type(create_body.HostConfig.Sysctls) == "table" then default_config.sysctl = {} @@ -193,8 +219,7 @@ elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then end local m = SimpleForm("docker", translate("Docker")) -m.template = "dockerman/cbi/xsimpleform" -m.redirect = luci.dispatcher.build_url("admin", "services","docker", "containers") +m.redirect = luci.dispatcher.build_url("admin", "docker", "containers") -- m.reset = false -- m.submit = false -- new Container @@ -269,14 +294,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 = "dockerman/cbi/xdynlist" +d.cfgvalue = function (self, section) return default_config.link or nil end 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.cfgvalue = function (self, section) return default_config.dns or nil end d.placeholder = "8.8.8.8" d.rmempty = true d.default = default_config.dns or nil @@ -287,19 +312,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 = "dockerman/cbi/xdynlist" +d.cfgvalue = function (self, section) return default_config.env or nil end d.placeholder = "TZ=Asia/Shanghai" d.rmempty = true d.default = default_config.env or nil d = s:option(DynamicList, "volume", translate("Bind Mount(-v)"), translate("Bind mount a volume")) -d.template = "dockerman/cbi/xdynlist" +d.cfgvalue = function (self, section) return default_config.volume or nil end d.placeholder = "/media:/media:slave" d.rmempty = true d.default = default_config.volume or nil local d_publish = s:option(DynamicList, "publish", translate("Exposed Ports(-p)"), translate("Publish container's port(s) to the host")) -d_publish.template = "dockerman/cbi/xdynlist" +d_publish.cfgvalue = function (self, section) return default_config.publish or nil end d_publish.placeholder = "2200:22/tcp" d_publish.rmempty = true d_publish.default = default_config.publish or nil @@ -321,26 +346,33 @@ 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.cfgvalue = function (self, section) return default_config.device or nil end 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.cfgvalue = function (self, section) return default_config.tmpfs or nil end 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(DynamicList, "sysctl", translate("Sysctl(--sysctl)"), translate("Sysctls (kernel parameters) options")) -d.template = "dockerman/cbi/xdynlist" +d.cfgvalue = function (self, section) return default_config.sysctl or nil end d.placeholder = "net.ipv4.ip_forward=1" d.rmempty = true d:depends("advance", 1) d.default = default_config.sysctl or nil +d = s:option(DynamicList, "cap_add", translate("CAP-ADD(--cap-add)"), translate("A list of kernel capabilities to add to the container")) +d.cfgvalue = function (self, section) return default_config.cap_add or nil end +d.placeholder = "NET_ADMIN" +d.rmempty = true +d:depends("advance", 1) +d.default = default_config.cap_add 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 @@ -368,7 +400,6 @@ d:depends("advance", 1) d.datatype="uinteger" d.default = default_config.blkio_weight or nil - for _, v in ipairs (networks) do if v.Name then local parent = v.Options and v.Options.parent or nil @@ -403,6 +434,7 @@ m.handle = function(self, state, data) local restart = data.restart local env = data.env local dns = data.dns + local cap_add = data.cap_add local sysctl = {} tmp = data.sysctl if type(tmp) == "table" then @@ -499,16 +531,16 @@ m.handle = function(self, state, data) 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.Cmd = command create_body.Env = env create_body.Image = image - create_body.ExposedPorts = (next(exposedports) ~= nil) and exposedports or nil + create_body.ExposedPorts = exposedports create_body.HostConfig = create_body.HostConfig or {} create_body.HostConfig.Dns = dns - create_body.HostConfig.Binds = (#volume ~= 0) and volume or nil + create_body.HostConfig.Binds = volume 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.PortBindings = portbindings create_body.HostConfig.Memory = tonumber(memory) create_body.HostConfig.CpuShares = tonumber(cpu_shares) create_body.HostConfig.NanoCPUs = tonumber(cpus) * 10 ^ 9 @@ -537,11 +569,12 @@ m.handle = function(self, state, data) -- 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 - create_body["HostConfig"]["Sysctls"] = (next(sysctl) ~= nil) and sysctl or nil + create_body["HostConfig"]["Tmpfs"] = tmpfs + create_body["HostConfig"]["Devices"] = device + create_body["HostConfig"]["Sysctls"] = sysctl + create_body["HostConfig"]["CapAdd"] = cap_add - if network == "bridge" and next(link) ~= nil then + if network == "bridge" then create_body["HostConfig"]["Links"] = link end local pull_image = function(image) @@ -551,8 +584,9 @@ m.handle = function(self, state, data) if res and res.code == 200 and (res.body[#res.body] and not res.body[#res.body].error and res.body[#res.body].status and (res.body[#res.body].status == "Status: Downloaded newer image for ".. image or res.body[#res.body].status == "Status: Image is up to date for ".. image)) then docker:append_status("done\n") else + res.code = (res.code == 200) and 500 or res.code docker:append_status("code:" .. res.code.." ".. (res.body[#res.body] and res.body[#res.body].error or (res.body.message or res.message)).. "\n") - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newcontainer")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer")) end end docker:clear_status() @@ -571,15 +605,16 @@ m.handle = function(self, state, data) end end + create_body = docker.clear_empty_tables(create_body) 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")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/containers")) else docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newcontainer")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer")) end end -return m +return m \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua index 5216be4300..79bf779c12 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua @@ -4,13 +4,11 @@ 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") +m.redirect = luci.dispatcher.build_url("admin", "docker", "networks") docker_status = m:section(SimpleSection) docker_status.template = "dockerman/apply_widget" @@ -35,7 +33,12 @@ d:value("overlay", "overlay") d = s:option(Value, "parent", translate("Parent Interface")) d.rmempty = true d:depends("dirver", "macvlan") -d.placeholder="eth0" +local interfaces = luci.sys and luci.sys.net and luci.sys.net.devices() or {} +for _, v in ipairs(interfaces) do + d:value(v, v) +end +d.default="br-lan" +d.placeholder="br-lan" d = s:option(Value, "macvlan_mode", translate("Macvlan Mode")) d.rmempty = true @@ -61,16 +64,24 @@ 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:depends("dirver", "overlay") d.disabled = 0 d.enabled = 1 d.default = 0 +if nixio.fs.access("/etc/config/network") and nixio.fs.access("/etc/config/firewall")then + d = s:option(Flag, "op_macvlan", translate("Create macvlan interface"), translate("Auto create macvlan interface in Openwrt")) + d:depends("dirver", "macvlan") + d.disabled = 0 + d.enabled = 1 + d.default = 1 +end + d = s:option(Value, "subnet", translate("Subnet")) d.rmempty = true d.placeholder="10.1.0.0/16" @@ -87,7 +98,6 @@ 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" @@ -152,14 +162,11 @@ m.handle = function(self, state, data) Subnet = subnet, Gateway = gateway, IPRange = ip_range, - -- AuxAddress = aux_address - -- AuxiliaryAddresses = aux_address + 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, @@ -191,16 +198,20 @@ m.handle = function(self, state, data) end end + create_body = docker.clear_empty_tables(create_body) docker:write_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")) + if driver == "macvlan" and data.op_macvlan ~= 0 then + docker.create_macvlan_interface(data.name, data.parent, data.gateway, data.ip_range) + end + luci.http.redirect(luci.dispatcher.build_url("admin/docker/networks")) else docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "\n") - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/newnetwork")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newnetwork")) end end end -return m +return m \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua index 7c4fd3befd..086a8597ba 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua @@ -18,7 +18,7 @@ function byte_format(byte) end end -local map_dockerman = Map("dockerman", translate("Docker")) +local map_dockerman = Map("dockerman", translate("Docker"), translate("DockerMan is a Simple Docker manager client for LuCI, If you have any issue please visit:") .. " ".. [[]] ..translate("Github") .. [[]]) local docker_info_table = {} -- docker_info_table['0OperatingSystem'] = {_key=translate("Operating System"),_value='-'} -- docker_info_table['1Architecture'] = {_key=translate("Architecture"),_value='-'} @@ -41,10 +41,11 @@ s.containers_total = '-' s.images_total = '-' s.networks_total = '-' s.volumes_total = '-' +local containers_list -- local socket = luci.model.uci.cursor():get("dockerman", "local", "socket_path") if (require "luci.model.docker").new():_ping().code == 200 then local dk = docker.new() - local containers_list = dk.containers:list({query = {all=true}}).body + 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 {} @@ -81,69 +82,71 @@ if (require "luci.model.docker").new():_ping().code == 200 then end s.template = "dockerman/overview" ---tabs -tab_section = map_dockerman:section(SimpleSection) -tab_section.tabs = { - dockerman = translate("DockerMan"), -} -tab_section.default_tab = "dockerman" -tab_section.template="dockerman/overview_tab" +local section_dockerman = map_dockerman:section(NamedSection, "local", "section", translate("Setting")) +section_dockerman:tab("dockerman", translate("DockerMan"), translate("DockerMan Settings")) +section_dockerman:tab("ac", translate("Access Control"), translate("Access Control for the bridge network")) +section_dockerman:tab("daemon", translate("Docker Daemon"), translate("Docker Daemon Settings")) -local section_dockerman = map_dockerman:section(NamedSection, "local", "section") -section_dockerman.config = "dockerman" -section_dockerman.template = "dockerman/cbi/namedsection" -local socket_path = section_dockerman:option(Value, "socket_path", translate("Docker Socket Path")) +local socket_path = section_dockerman:taboption("dockerman", Value, "socket_path", translate("Docker Socket Path")) socket_path.default = "/var/run/docker.sock" socket_path.placeholder = "/var/run/docker.sock" socket_path.rmempty = false -local remote_endpoint = section_dockerman:option(Flag, "remote_endpoint", translate("Remote Endpoint"), translate("Dockerman connect to remote endpoint")) +local remote_endpoint = section_dockerman:taboption("dockerman", Flag, "remote_endpoint", translate("Remote Endpoint"), translate("Dockerman connect to remote endpoint")) remote_endpoint.rmempty = false remote_endpoint.enabled = "true" remote_endpoint.disabled = "false" -local remote_host = section_dockerman:option(Value, "remote_host", translate("Remote Host")) +local remote_host = section_dockerman:taboption("dockerman", Value, "remote_host", translate("Remote Host")) remote_host.placeholder = "10.1.1.2" -- remote_host:depends("remote_endpoint", "true") -local remote_port = section_dockerman:option(Value, "remote_port", translate("Remote Port")) +local remote_port = section_dockerman:taboption("dockerman", Value, "remote_port", translate("Remote Port")) remote_port.placeholder = "2375" remote_port.default = "2375" -- remote_port:depends("remote_endpoint", "true") -local status_path = section_dockerman:option(Value, "status_path", translate("Action Status Tempfile Path"), translate("Where you want to save the docker status file")) -local debug = section_dockerman: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" -local debug_path = section_dockerman:option(Value, "debug_path", translate("Debug Tempfile Path"), translate("Where you want to save the debug tempfile")) +-- local status_path = section_dockerman:taboption("dockerman", Value, "status_path", translate("Action Status Tempfile Path"), translate("Where you want to save the docker status file")) +-- local debug = section_dockerman:taboption("dockerman", 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" +-- local debug_path = section_dockerman:taboption("dockerman", Value, "debug_path", translate("Debug Tempfile Path"), translate("Where you want to save the debug tempfile")) -local map_dockerd -if nixio.fs.access("/etc/config/dockerd") and nixio.fs.access("/usr/bin/dockerd") then - -- map_dockerman:chain("dockerd") - tab_section.tabs.docker_daemon = translate("Docker Daemon") - tab_section.default_tab = "docker_daemon" - map_dockerd = Map("dockerd","") - local section_dockerd = map_dockerd:section(NamedSection, "local", "section") - section_dockerd.config = "docker_daemon" - section_dockerd.template = "dockerman/cbi/namedsection" - local dockerd_enable = section_dockerd:option(Flag, "ea", translate("Enable")) +if nixio.fs.access("/usr/bin/dockerd") then + local allowed_interface = section_dockerman:taboption("ac", DynamicList, "ac_allowed_interface", translate("Allowed access interfaces"), translate("Which interface(s) can access containers under the bridge network, fill-in Interface Name")) + local interfaces = luci.sys and luci.sys.net and luci.sys.net.devices() or {} + for i, v in ipairs(interfaces) do + allowed_interface:value(v, v) + end + local allowed_container = section_dockerman:taboption("ac", DynamicList, "ac_allowed_container", translate("Containers allowed to be accessed"), translate("Which container(s) can be accessed, even from interfaces that are not allowed, fill-in Container Id or Name")) + allowed_container.placeholder = "container name_or_id" + if containers_list then + for i, v in ipairs(containers_list) do + if v.State == "running" and v.NetworkSettings and v.NetworkSettings.Networks and v.NetworkSettings.Networks.bridge and v.NetworkSettings.Networks.bridge.IPAddress then + allowed_container:value(v.Id:sub(1,12), v.Names[1]:sub(2) .. " | " .. v.NetworkSettings.Networks.bridge.IPAddress) + end + end + end + + local dockerd_enable = section_dockerman:taboption("daemon", Flag, "daemon_ea", translate("Enable")) dockerd_enable.enabled = "true" dockerd_enable.rmempty = true - local data_root = section_dockerd:option(Value, "data_root", translate("Docker Root Dir")) + local data_root = section_dockerman:taboption("daemon", Value, "daemon_data_root", translate("Docker Root Dir")) data_root.placeholder = "/opt/docker/" - local hosts = section_dockerd:option(DynamicList, "hosts", translate("Server Host"), translate('Daemon unix socket (unix:///var/run/docker.sock) or TCP Remote Hosts (tcp://0.0.0.0:2375), default: unix:///var/run/docker.sock')) - hosts.placeholder = "unix:///var/run/docker.sock | tcp://0.0.0.0:2375" - hosts.rmempty = true - local registry_mirrors = section_dockerd:option(DynamicList, "registry_mirrors", translate("Registry Mirrors")) + local registry_mirrors = section_dockerman:taboption("daemon", DynamicList, "daemon_registry_mirrors", translate("Registry Mirrors")) registry_mirrors.placeholder = "https://hub-mirror.c.163.com" - local wan_enable = section_dockerd:option(Flag, "en_wan", translate("Enable WAN access"), translate("Enable WAN access container mapped ports")) - wan_enable.enabled = "true" - wan_enable.rmempty = true - local log_level = section_dockerd:option(ListValue, "log_level", translate("Log Level"), translate('Set the logging level')) + registry_mirrors:value("https://hub-mirror.c.163.com", "https://hub-mirror.c.163.com") + + local log_level = section_dockerman:taboption("daemon", ListValue, "daemon_log_level", translate("Log Level"), translate('Set the logging level')) log_level:value("debug", "debug") log_level:value("info", "info") log_level:value("warn", "warn") log_level:value("error", "error") log_level:value("fatal", "fatal") + local hosts = section_dockerman:taboption("daemon", DynamicList, "daemon_hosts", translate("Server Host"), translate('Daemon unix socket (unix:///var/run/docker.sock) or TCP Remote Hosts (tcp://0.0.0.0:2375), default: unix:///var/run/docker.sock')) + hosts.placeholder = "unix:///var/run/docker.sock" + hosts:value("unix:///var/run/docker.sock", "unix:///var/run/docker.sock") + hosts:value("tcp://0.0.0.0:2375", "tcp://0.0.0.0:2375") + hosts.rmempty = true end -return map_dockerman, map_dockerd +return map_dockerman \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua index ca8111a28b..2374969056 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua @@ -28,7 +28,7 @@ function get_volumes() 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)..'' + ''.. cv.Names[1]:sub(2)..'' end end end @@ -50,7 +50,6 @@ 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 @@ -111,7 +110,7 @@ btnremove.write = function(self, section) end end if success then docker:clear_status() end - luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/volumes")) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/volumes")) end end -return m +return m \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/model/docker.lua b/package/ctcgfw/luci-app-dockerman/luasrc/model/docker.lua index 305089e248..4728509418 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/model/docker.lua +++ b/package/ctcgfw/luci-app-dockerman/luasrc/model/docker.lua @@ -79,14 +79,14 @@ local map_subtract = function(t1, t2) return next(res) ~= nil and res or nil end -local function clear_empty_tables( t ) +_docker.clear_empty_tables = function ( t ) local k, v if next(t) == nil then t = nil else for k, v in pairs(t) do if type(v) == 'table' then - t[k] = clear_empty_tables(v) + t[k] = _docker.clear_empty_tables(v) end end end @@ -150,8 +150,8 @@ local get_config = function(container_config, image_config) local create_body = config create_body["HostConfig"] = host_config create_body["NetworkingConfig"] = {EndpointsConfig = network_setting} - create_body = clear_empty_tables(create_body) or {} - extra_network = clear_empty_tables(extra_network) or {} + create_body = _docker.clear_empty_tables(create_body) or {} + extra_network = _docker.clear_empty_tables(extra_network) or {} return create_body, extra_network end @@ -308,23 +308,23 @@ end --{"status":"Downloading from https://downloads.openwrt.org/releases/19.07.0/targets/x86/64/openwrt-19.07.0-x86-64-generic-rootfs.tar.gz"} --{"status":"Importing","progressDetail":{"current":1572391,"total":3821714},"progress":"[====================\u003e ] 1.572MB/3.822MB"} --{"status":"sha256:d5304b58e2d8cc0a2fd640c05cec1bd4d1229a604ac0dd2909f13b2b47a29285"} --- _docker.import_image_show_status_cb = function(res, source) --- return status_cb(res, source, function(chunk) --- local json_parse = luci.jsonc.parse --- local step = json_parse(chunk) --- if type(step) == "table" then --- local buf = _docker:read_status() --- local num = 0 --- local str = '\t' .. (step.status and step.status or "") .. (step.progress and (" " .. step.progress) or "").."\n" --- if step.status then buf, num = buf:gsub("\t"..step.status .. " .-\n", str) end --- if num == 0 then --- buf = buf .. str --- end --- _docker:write_status(buf) --- end --- end --- ) --- end +_docker.import_image_show_status_cb = function(res, source) + return status_cb(res, source, function(chunk) + local json_parse = luci.jsonc.parse + local step = json_parse(chunk) + if type(step) == "table" then + local buf = _docker:read_status() + local num = 0 + local str = '\t' .. (step.status and step.status or "") .. (step.progress and (" " .. step.progress) or "").."\n" + if step.status then buf, num = buf:gsub("\t"..step.status .. " .-\n", str) end + if num == 0 then + buf = buf .. str + end + _docker:write_status(buf) + end + end + ) +end -- _docker.print_status_cb = function(res, source) -- return status_cb(res, source, function(step) @@ -333,4 +333,70 @@ end -- ) -- end -return _docker +_docker.create_macvlan_interface = function(name, device, gateway, ip_range) + if not nixio.fs.access("/etc/config/network") or not nixio.fs.access("/etc/config/firewall") then return end + if uci:get("dockerman", "local", "remote_endpoint") == "true" then return end + local ip = require "luci.ip" + local if_name = "docker_"..name + local dev_name = "macvlan_"..name + local net_mask = tostring(ip.new(ip_range):mask()) + local lan_interfaces + -- add macvlan device + uci:delete("network", dev_name) + uci:set("network", dev_name, "device") + uci:set("network", dev_name, "name", dev_name) + uci:set("network", dev_name, "ifname", device) + uci:set("network", dev_name, "type", "macvlan") + uci:set("network", dev_name, "mode", "bridge") + -- add macvlan interface + uci:delete("network", if_name) + uci:set("network", if_name, "interface") + uci:set("network", if_name, "proto", "static") + uci:set("network", if_name, "ifname", dev_name) + uci:set("network", if_name, "ipaddr", gateway) + uci:set("network", if_name, "netmask", net_mask) + uci:foreach("firewall", "zone", function(s) + if s.name == "lan" then + local interfaces + if type(s.network) == "table" then + interfaces = table.concat(s.network, " ") + uci:delete("firewall", s[".name"], "network") + else + interfaces = s.network and s.network or "" + end + interfaces = interfaces .. " " .. if_name + interfaces = interfaces:gsub("%s+", " ") + uci:set("firewall", s[".name"], "network", interfaces) + end + end) + uci:commit("firewall") + uci:commit("network") + os.execute("ifup " .. if_name) +end + +_docker.remove_macvlan_interface = function(name) + if not nixio.fs.access("/etc/config/network") or not nixio.fs.access("/etc/config/firewall") then return end + if uci:get("dockerman", "local", "remote_endpoint") == "true" then return end + local if_name = "docker_"..name + local dev_name = "macvlan_"..name + uci:foreach("firewall", "zone", function(s) + if s.name == "lan" then + local interfaces + if type(s.network) == "table" then + interfaces = table.concat(s.network, " ") + else + interfaces = s.network and s.network or "" + end + interfaces = interfaces and interfaces:gsub(if_name, "") + interfaces = interfaces and interfaces:gsub("%s+", " ") + uci:set("firewall", s[".name"], "network", interfaces) + end + end) + uci:commit("firewall") + uci:delete("network", dev_name) + uci:delete("network", if_name) + uci:commit("network") + os.execute("ip link del " .. if_name) +end + +return _docker \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm index f7fb310e0b..334c76a1bd 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm @@ -78,7 +78,7 @@ function docker_status_message(type, content) { XHR.run(); } } -var loading_msg="Loadding.." +var loading_msg="Loading.." function uci_confirm_docker() { var tt; docker_status_message('notice'); @@ -95,7 +95,7 @@ function uci_confirm_docker() { // var delay = isNaN(duration) ? 0 : Math.max(1000 - duration, 0); var delay =1000 window.setTimeout(function() { - xhr.get('<%=url("admin/services/docker/confirm")%>', null, call, uci_apply_timeout * 1000); + xhr.get('<%=url("admin/docker/confirm")%>', null, call, uci_apply_timeout * 1000); }, delay); }; @@ -103,7 +103,7 @@ function uci_confirm_docker() { var now = Date.now(); docker_status_message('notice', - ' ' + + ' ' + loading_msg + ''); tt = window.setTimeout(tick, 200); @@ -124,7 +124,7 @@ function fnSubmitForm(el){ } <% if self.err then -%> - docker_status_message('warning', ''+`<%=self.err%>`+''); + docker_status_message('warning', ''+`<%=self.err%>`+''); document.getElementById('docker_apply_overlay').addEventListener("click", (e)=>{ docker_status_message() }) @@ -137,4 +137,4 @@ var buttons = document.querySelectorAll('input[type="submit"]'); }); } -//]]> +//]]> \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/cbi/xdynlist.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/cbi/xdynlist.htm deleted file mode 100644 index 549c4ce319..0000000000 --- a/package/ctcgfw/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/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/cbi/xsimpleform.htm deleted file mode 100644 index 7cfe8bf218..0000000000 --- a/package/ctcgfw/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/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container.htm index 4d068dbf84..afa000e00e 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container.htm @@ -9,18 +9,18 @@ + \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_console.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_console.htm index 636aec9605..0b9fc4ce66 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_console.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_console.htm @@ -3,4 +3,4 @@ + \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_file.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_file.htm index b00746f68b..dc4885f431 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_file.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_file.htm @@ -33,7 +33,7 @@ formData.append('upload-path', uploadPath) formData.append('upload-archive', uploadArchive.files[0]) let xhr = new XMLHttpRequest() - xhr.open("POST", "/cgi-bin/luci/admin/services/docker/container_put_archive/<%=self.container%>", true) + xhr.open("POST", "/cgi-bin/luci/admin/docker/container_put_archive/<%=self.container%>", true) xhr.onload = function() { if (xhr.status == 200) { uploadArchive.value = '' @@ -58,6 +58,6 @@ }) return } - window.open("/cgi-bin/luci/admin/services/docker/container_get_archive/?id=<%=self.container%>&path=" + encodeURIComponent(downloadPath)) + window.open("/cgi-bin/luci/admin/docker/container_get_archive/?id=<%=self.container%>&path=" + encodeURIComponent(downloadPath)) } - + \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm index 2016181c58..5320db9dbf 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm @@ -22,7 +22,7 @@ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } - XHR.poll(5, '/cgi-bin/luci/admin/services/docker/container_stats/<%=self.container_id%>', { status: 1 }, + XHR.poll(5, '/cgi-bin/luci/admin/docker/container_stats/<%=self.container_id%>', { status: 1 }, function (x, info) { var e; @@ -57,4 +57,4 @@ } }); -//]]> +//]]> \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/images_import.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/images_import.htm index e68724f226..06124718b5 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/images_import.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/images_import.htm @@ -1,5 +1,3 @@ - -
@@ -21,7 +19,7 @@ formData.append('tag', valITag.value) let xhr = new XMLHttpRequest() uci_confirm_docker() - xhr.open("POST", "<%=url('admin/services/docker/images_import')%>", true) + xhr.open("POST", "<%=url('admin/docker/images_import')%>", true) xhr.onload = function () { location.reload() } @@ -42,7 +40,7 @@ formData.append('upload-archive', fileimport.files[0]) let xhr = new XMLHttpRequest() uci_confirm_docker() - xhr.open("POST", "<%=url('admin/services/docker/images_import')%>", true) + xhr.open("POST", "<%=url('admin/docker/images_import')%>", true) xhr.onload = function () { fileimport.value = '' location.reload() @@ -53,7 +51,7 @@ let new_tag = function (image_id) { let new_tag = prompt("<%:New tag%>\n<%:Image%>" + "ID: " + image_id + "\n<%:Please input new tag%>:", "") if (new_tag) { - (new XHR()).post("<%=url('admin/services/docker/images_tag')%>", + (new XHR()).post("<%=url('admin/docker/images_tag')%>", { id: image_id, tag: new_tag }, function (r) { if (r.status == 201) { @@ -72,7 +70,7 @@ let un_tag = function (tag) { if (tag.match("")) return if (confirm("<%:Remove tag%>: " + tag + " ?")) { - (new XHR()).post("<%=url('admin/services/docker/images_untag')%>", + (new XHR()).post("<%=url('admin/docker/images_untag')%>", { tag: tag }, function (r) { if (r.status == 200) { @@ -87,4 +85,4 @@ }) } } - + \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/images_load.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/images_load.htm index 043b60d8d5..51a2e39cbe 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/images_load.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/images_load.htm @@ -20,7 +20,7 @@ formData.append('upload-archive', fileLoad.files[0]) let xhr = new XMLHttpRequest() uci_confirm_docker() - xhr.open("POST", "/cgi-bin/luci/admin/services/docker/images_load", true) + xhr.open("POST", "/cgi-bin/luci/admin/docker/images_load", true) xhr.onload = function() { location.reload() } diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/logs.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/logs.htm index 8e94cad42d..c9035daf7c 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/logs.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/logs.htm @@ -8,4 +8,4 @@
<% if self.title == "Events" then %> <%+footer%> -<% end %> +<% end %> \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm index e26bacf33f..52a25d1981 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm @@ -73,7 +73,7 @@ let reg_rem =/`#.+`/g// the command has `# ` cmd_line = cmd_line.replace(/^docker\s+(run|create)/,"DOCKERCLI").replace(reg_rem, " ").replace(reg_muti_line, " ").replace(reg_space, " ") console.log(cmd_line) - window.location.href = "/cgi-bin/luci/admin/services/docker/newcontainer/" + encodeURI(cmd_line) + window.location.href = "/cgi-bin/luci/admin/docker/newcontainer/" + encodeURI(cmd_line) } function clear_text(){ @@ -92,4 +92,4 @@ <%+cbi/valueheader%> -<%+cbi/valuefooter%> +<%+cbi/valuefooter%> \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/overview.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/overview.htm index c2d6e6a7b8..81557dfb87 100644 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/overview.htm +++ b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/overview.htm @@ -136,7 +136,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md

<%:Containers%>

- <%- if self.containers_total ~= "-" then -%><%- end -%> + <%- if self.containers_total ~= "-" then -%><%- end -%> <%=self.containers_running%> /<%=self.containers_total%> <%- if self.containers_total ~= "-" then -%><%- end -%> @@ -160,7 +160,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md

<%:Images%>

- <%- if self.images_total ~= "-" then -%><%- end -%> + <%- if self.images_total ~= "-" then -%><%- end -%> <%=self.images_used%> /<%=self.images_total%> <%- if self.images_total ~= "-" then -%><%- end -%> @@ -192,7 +192,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md

<%:Networks%>

- <%- if self.networks_total ~= "-" then -%><%- end -%> + <%- if self.networks_total ~= "-" then -%><%- end -%> <%=self.networks_total%> <%- if self.networks_total ~= "-" then -%><%- end -%> @@ -269,7 +269,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md

<%:Volumes%>

- <%- if self.volumes_total ~= "-" then -%><%- end -%> + <%- if self.volumes_total ~= "-" then -%><%- end -%> <%=self.volumes_total%> <%- if self.volumes_total ~= "-" then -%><%- end -%> @@ -277,4 +277,4 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md

-

+ \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/overview_tab.htm b/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/overview_tab.htm deleted file mode 100644 index a85c15bb1a..0000000000 --- a/package/ctcgfw/luci-app-dockerman/luasrc/view/dockerman/overview_tab.htm +++ /dev/null @@ -1,31 +0,0 @@ -
-

<%:Setting%>

-
    - <% for k, v in pairs(self.tabs) do - local class = k == self.default_tab and "cbi-tab" or "cbi-tab-disabled" - local id = "tab.overview-tab." .. k - %> -
  • class=<%=class%> > - <%=v%> -
  • - <% end %> -
- diff --git a/package/ctcgfw/luci-app-dockerman/po/zh_Hans/dockerman.po b/package/ctcgfw/luci-app-dockerman/po/zh_Hans/dockerman.po index 40f377f435..73e8c11b67 100644 --- a/package/ctcgfw/luci-app-dockerman/po/zh_Hans/dockerman.po +++ b/package/ctcgfw/luci-app-dockerman/po/zh_Hans/dockerman.po @@ -411,3 +411,33 @@ msgstr "错误" msgid "Console" msgstr "控制台" + +msgid "DockerMan is a Simple Docker manager client for LuCI, If you have any issue please visit:" +msgstr "DockerMan 是一个简单的 Docker 管理客户端,如果您在使用过程中有问题,请访问:" + +msgid "Access Control for the bridge network" +msgstr "birdge 网络访问控制" + +msgid "Allowed access interfaces" +msgstr "允许访问的接口" + +msgid "Containers allowed to be accessed" +msgstr "允许被访问的容器" + +msgid "Which container(s) can be accessed, even from interfaces that are not allowed, fill-in Container Id or Name" +msgstr "哪些容器可以被访问,即使访问来自不被允许的接口,填入容器ID或容器名" + +msgid "Which interface(s) can access containers under the bridge network, fill-in Interface Name" +msgstr "哪些接口可以访问 bridge 网络下的容器, 填入接口名" + +msgid "Dockerman connect to remote endpoint" +msgstr "Dockerman 将连接到远程节点" + +msgid "Access Control" +msgstr "访问控制" + +msgid "Create macvlan interface" +msgstr "创建 macvlan 接口" + +msgid "Auto create macvlan interface in Openwrt" +msgstr "在 Openwrt 中自动创建 macvlan 接口" \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/root/etc/config/dockerd b/package/ctcgfw/luci-app-dockerman/root/etc/config/dockerd deleted file mode 100644 index d0ae9596d8..0000000000 --- a/package/ctcgfw/luci-app-dockerman/root/etc/config/dockerd +++ /dev/null @@ -1,5 +0,0 @@ -config section 'local' - option ea 'true' - option en_wan 'false' - option data_root '/opt/docker' - option log_level 'warn' diff --git a/package/ctcgfw/luci-app-dockerman/root/etc/config/dockerman b/package/ctcgfw/luci-app-dockerman/root/etc/config/dockerman index f13c5c205e..63e30bf24c 100644 --- a/package/ctcgfw/luci-app-dockerman/root/etc/config/dockerman +++ b/package/ctcgfw/luci-app-dockerman/root/etc/config/dockerman @@ -1,5 +1,10 @@ config section 'local' option socket_path '/var/run/docker.sock' option status_path '/tmp/.docker_action_status' - option debug_path '/tmp/.docker_debug' option debug 'false' + option debug_path '/tmp/.docker_debug' + option remote_endpoint 'false' + option daemon_ea 'true' + option daemon_data_root '/opt/docker' + option daemon_log_level 'warn' + list ac_allowed_interface 'br-lan' diff --git a/package/ctcgfw/luci-app-dockerman/root/etc/docker-init b/package/ctcgfw/luci-app-dockerman/root/etc/docker-init deleted file mode 100755 index 45b9769a51..0000000000 --- a/package/ctcgfw/luci-app-dockerman/root/etc/docker-init +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -dtype=`fdisk -l /dev/sda | grep 'Disklabel type' | awk '{print $3}'` -partid="0" - -if [ "$dtype" = "gpt" ] -then - partid=`echo "n - - - -w -" | fdisk /dev/sda | grep 'Created a new partition' | awk '{print $5}'` - -elif [ "$dtype" = "dos" ] -then - partid=`echo "n -p - - - -w -" | fdisk /dev/sda | grep 'Created a new partition' | awk '{print $5}'` -fi - -echo "y" | mkfs.ext4 /dev/sda$partid diff --git a/package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerd b/package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerd deleted file mode 100755 index 777f246ec9..0000000000 --- a/package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerd +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh /etc/rc.common - -USE_PROCD=1 -START=99 -NAME=dockerd_local -DOCKERD_CONF="/etc/docker/daemon.json" - -append_list_item() { - append "$2" "$1" "\",\"" -} - -get_config() { - config_load $1 - config_get ea "local" ea - config_get en_wan "local" en_wan - config_get data_root "local" data_root '/opt/docker' - config_get log_level "local" log_level 'warn' - config_list_foreach "local" registry_mirrors append_list_item registry_mirrors - config_list_foreach "local" hosts append_list_item hosts -} - -gen_config(){ - cat <<-EOF >$DOCKERD_CONF -{ - "data-root": "$data_root", - "log-level": "$log_level", - "registry-mirrors": ["$registry_mirrors"], - "hosts": ["$hosts"] -} -EOF -sed -i 's/\[\"\"\]/\[\]/g' $DOCKERD_CONF -} - -_start() { - local nofile=$(cat /proc/sys/fs/nr_open) - get_config dockerd - gen_config - if [ -n "$en_wan" ]; then - iptables -D DOCKER-USER ! -i br-lan -m conntrack --ctstate NEW,INVALID -o docker0 -j DROP >/dev/null 2>&1 - iptables -D DOCKER-USER ! -i br-lan -m conntrack --ctstate ESTABLISHED,RELATED -o docker0 -j RETURN >/dev/null 2>&1 - else - iptables -D DOCKER-USER ! -i br-lan -m conntrack --ctstate NEW,INVALID -o docker0 -j DROP >/dev/null 2>&1 - iptables -D DOCKER-USER ! -i br-lan -m conntrack --ctstate ESTABLISHED,RELATED -o docker0 -j RETURN >/dev/null 2>&1 - iptables -I DOCKER-USER ! -i br-lan -m conntrack --ctstate ESTABLISHED,RELATED -o docker0 -j RETURN >/dev/null 2>&1 - iptables -I DOCKER-USER ! -i br-lan -m conntrack --ctstate NEW,INVALID -o docker0 -j DROP >/dev/null 2>&1 - fi - if [ -n "$ea" ]; then - procd_open_instance $NAME - procd_set_param stderr 1 - procd_set_param command /usr/bin/dockerd - procd_set_param limits nofile="${nofile} ${nofile}" - procd_close_instance - fi -} - -start_service() { - _start -} - -service_triggers() { - procd_add_reload_trigger dockerd -} - -reload_service() { - restart -} diff --git a/package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerman b/package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerman new file mode 100755 index 0000000000..285486d550 --- /dev/null +++ b/package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerman @@ -0,0 +1,45 @@ +#!/bin/sh /etc/rc.common + +START=99 +DOCKERD_CONF="/etc/docker/daemon.json" + +config_load dockerman +config_get daemon_ea "local" daemon_ea + +init_dockerman_chain(){ + iptables -N DOCKER-MAN >/dev/null 2>&1 + iptables -F DOCKER-MAN >/dev/null 2>&1 + iptables -D DOCKER-USER -j DOCKER-MAN >/dev/null 2>&1 + iptables -I DOCKER-USER -j DOCKER-MAN >/dev/null 2>&1 +} + +add_allowed_interface(){ + iptables -A DOCKER-MAN -i $1 -o docker0 -j RETURN +} + +add_allowed_ip(){ + iptables -A DOCKER-MAN -d $1 -o docker0 -j RETURN +} + +handle_allowed_interface(){ + #config_list_foreach "local" allowed_ip add_allowed_ip + config_list_foreach "local" ac_allowed_interface add_allowed_interface + iptables -A DOCKER-MAN -m conntrack --ctstate ESTABLISHED,RELATED -o docker0 -j RETURN >/dev/null 2>&1 + iptables -A DOCKER-MAN -m conntrack --ctstate NEW,INVALID -o docker0 -j DROP >/dev/null 2>&1 + iptables -A DOCKER-MAN -j RETURN >/dev/null 2>&1 +} + +start(){ + init_dockerman_chain + if [ -n "$daemon_ea" ]; then + handle_allowed_interface + lua /usr/share/dockerman/dockerd-config.lua "$DOCKERD_CONF" && /etc/init.d/dockerd restart && sleep 5 || { + # 1 running, 0 stopped + STATE=$([ -n "$(ps |grep /usr/bin/dockerd | grep -v grep)" ] && echo 1 || echo 0) + [ "$STATE" == "0" ] && /etc/init.d/dockerd start && sleep 5 + } + lua /usr/share/dockerman/dockerd-ac.lua + else + /etc/init.d/dockerd stop + fi +} diff --git a/package/ctcgfw/luci-app-dockerman/root/etc/uci-defaults/luci-app-dockerman b/package/ctcgfw/luci-app-dockerman/root/etc/uci-defaults/luci-app-dockerman index 9ad21a711f..1c67049cef 100755 --- a/package/ctcgfw/luci-app-dockerman/root/etc/uci-defaults/luci-app-dockerman +++ b/package/ctcgfw/luci-app-dockerman/root/etc/uci-defaults/luci-app-dockerman @@ -1,14 +1,14 @@ #!/bin/sh uci -q batch <<-EOF >/dev/null - set uhttpd.main.script_timeout="600" + set uhttpd.main.script_timeout="360" commit uhttpd - delete ucitrack.@dockerd[-1] - add ucitrack dockerd - set ucitrack.@dockerd[-1].init=dockerd + delete ucitrack.@dockerman[-1] + add ucitrack dockerman + set ucitrack.@dockerman[-1].exec='/etc/init.d/dockerman start' commit ucitrack EOF -/etc/init.d/dockerd enable >/dev/null 2>&1 +[ -x "$(which dockerd)" ] && chmod +x /etc/init.d/dockerman && /etc/init.d/dockerd disable && /etc/init.d/dockerman enable >/dev/null 2>&1 /etc/init.d/uhttpd restart >/dev/null 2>&1 rm -fr /tmp/luci-indexcache /tmp/luci-modulecache >/dev/null 2>&1 -exit 0 +exit 0 \ No newline at end of file diff --git a/package/ctcgfw/luci-app-dockerman/root/usr/share/dockerman/dockerd-ac.lua b/package/ctcgfw/luci-app-dockerman/root/usr/share/dockerman/dockerd-ac.lua new file mode 100644 index 0000000000..e8a2c0b7eb --- /dev/null +++ b/package/ctcgfw/luci-app-dockerman/root/usr/share/dockerman/dockerd-ac.lua @@ -0,0 +1,20 @@ +require "luci.util" +docker = require "luci.docker" +uci = (require "luci.model.uci").cursor() +dk = docker.new({socket_path = "/var/run/docker.sock"}) + +if dk:_ping().code ~= 200 then return end +containers_list = dk.containers:list({query = {all=true}}).body +allowed_container = uci:get("dockerman", "local", "ac_allowed_container") + +if not allowed_container or next(allowed_container)==nil then return end +allowed_ip = {} +for i, v in ipairs(containers_list) do + for ii, vv in ipairs(allowed_container) do + if v.Id:sub(1,12) == vv and v.NetworkSettings and v.NetworkSettings.Networks and v.NetworkSettings.Networks.bridge and v.NetworkSettings.Networks.bridge.IPAddress then + print(v.NetworkSettings.Networks.bridge.IPAddress) + luci.util.exec("iptables -I DOCKER-MAN -d "..v.NetworkSettings.Networks.bridge.IPAddress.." -o docker0 -j RETURN") + table.remove(allowed_container, ii) + end + end +end diff --git a/package/ctcgfw/luci-app-dockerman/root/usr/share/dockerman/dockerd-config.lua b/package/ctcgfw/luci-app-dockerman/root/usr/share/dockerman/dockerd-config.lua new file mode 100644 index 0000000000..16dcb00b43 --- /dev/null +++ b/package/ctcgfw/luci-app-dockerman/root/usr/share/dockerman/dockerd-config.lua @@ -0,0 +1,50 @@ +require "luci.util" +fs = require "nixio.fs" +uci = (require "luci.model.uci").cursor() + +raw_file_dir = arg[1] + +raw_json_str = fs.readfile(raw_file_dir) +raw_json = luci.jsonc.parse(raw_json_str) or {} + +new_json = {} +new_json["data-root"] = uci:get("dockerman", "local", "daemon_data_root") +new_json["hosts"] = uci:get("dockerman", "local", "daemon_hosts") +new_json["registry-mirrors"] = uci:get("dockerman", "local", "daemon_registry_mirrors") +new_json["log-level"] = uci:get("dockerman", "local", "daemon_log_level") + +function comp(raw, new) + for k, v in pairs(new) do + if type(v) == "table" and raw[k] then + if #v == #raw[k] then + comp(raw[k], v) + else + changed = true + raw[k] = v + end + elseif raw[k] ~= v then + changed = true + raw[k] = v + end + end + for k, v in ipairs(new) do + if type(v) == "table" and raw[k] then + if #v == #raw[k] then + comp(raw[k], v) + else + changed = true + raw[k] = v + end + elseif raw[k] ~= v then + changed = true + raw[k] = v + end + end +end +comp(raw_json, new_json) +if changed then + fs.writefile(raw_file_dir, luci.jsonc.stringify(raw_json, true):gsub("\\", "")) + os.exit(0) +else + os.exit(1) +end