luci-app-dockerman: sync with upstream source
This commit is contained in:
parent
c0fd0410cc
commit
28992ba615
@ -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 <https://github.com/lisaac/luci-app-dockerman>
|
||||
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)))
|
||||
|
||||
1
package/ctcgfw/luci-app-dockerman/depends.lst
Normal file
1
package/ctcgfw/luci-app-dockerman/depends.lst
Normal file
@ -0,0 +1 @@
|
||||
ttyd
|
||||
@ -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
|
||||
|
||||
@ -4,7 +4,6 @@ Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
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
|
||||
@ -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"] = '<a href='..luci.dispatcher.build_url("admin/services/docker/container/"..v.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. v.Names[1]:sub(2).."</a>"
|
||||
data[index]["_name"] = '<a href='..luci.dispatcher.build_url("admin/docker/container/"..v.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. v.Names[1]:sub(2).."</a>"
|
||||
data[index]["_status"] = v.Status
|
||||
if v.Status:find("^Up") then
|
||||
data[index]["_status"] = '<font color="green">'.. data[index]["_status"] .. "</font>"
|
||||
@ -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
|
||||
@ -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 "")..
|
||||
'<a href='..luci.dispatcher.build_url("admin/services/docker/container/"..cv.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. cv.Names[1]:sub(2).."</a>"
|
||||
'<a href='..luci.dispatcher.build_url("admin/docker/container/"..cv.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. cv.Names[1]:sub(2).."</a>"
|
||||
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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -4,13 +4,11 @@ Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
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
|
||||
@ -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:") .. " ".. [[<a href="https://github.com/lisaac/luci-app-dockerman" target="_blank">]] ..translate("Github") .. [[</a>]])
|
||||
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
|
||||
@ -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 "")..
|
||||
'<a href='..luci.dispatcher.build_url("admin/services/docker/container/"..cv.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. cv.Names[1]:sub(2)..'</a>'
|
||||
'<a href='..luci.dispatcher.build_url("admin/docker/container/"..cv.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. cv.Names[1]:sub(2)..'</a>'
|
||||
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
|
||||
@ -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
|
||||
@ -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',
|
||||
'<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> <span style="white-space:pre-line; font-family: \'Courier New\', Courier, monospace;">' +
|
||||
'<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> <span style="white-space:pre-line; word-break:break-all; font-family: \'Courier New\', Courier, monospace;">' +
|
||||
loading_msg + '</span>');
|
||||
|
||||
tt = window.setTimeout(tick, 200);
|
||||
@ -124,7 +124,7 @@ function fnSubmitForm(el){
|
||||
}
|
||||
|
||||
<% if self.err then -%>
|
||||
docker_status_message('warning', '<span style="white-space:pre-line; font-family: \'Courier New\', Courier, monospace;">'+`<%=self.err%>`+'</span>');
|
||||
docker_status_message('warning', '<span style="white-space:pre-line; word-break:break-all; font-family: \'Courier New\', Courier, monospace;">'+`<%=self.err%>`+'</span>');
|
||||
document.getElementById('docker_apply_overlay').addEventListener("click", (e)=>{
|
||||
docker_status_message()
|
||||
})
|
||||
@ -137,4 +137,4 @@ var buttons = document.querySelectorAll('input[type="submit"]');
|
||||
});
|
||||
}
|
||||
|
||||
//]]></script>
|
||||
//]]></script>
|
||||
@ -1,27 +0,0 @@
|
||||
<%+cbi/valueheader%>
|
||||
<div<%=
|
||||
attr("data-prefix", cbid) ..
|
||||
attr("data-browser-path", self.default_path) ..
|
||||
attr("data-dynlist", luci.util.serialize_json({
|
||||
self.keylist, self.vallist,
|
||||
self.datatype, self.optional or self.rmempty
|
||||
})) ..
|
||||
|
||||
ifattr(self.size, "data-size", self.size) ..
|
||||
ifattr(self.placeholder, "data-placeholder", self.placeholder)
|
||||
%>>
|
||||
<%
|
||||
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
|
||||
%>
|
||||
<input class="cbi-input-text" value="<%=pcdata(val)%>" data-update="change" type="text"<%=
|
||||
attr("id", cbid .. "." .. i) ..
|
||||
attr("name", cbid) ..
|
||||
ifattr(self.size, "size") ..
|
||||
ifattr(i == 1 and self.placeholder, "placeholder", self.placeholder)
|
||||
%> /><br />
|
||||
<% end end %>
|
||||
</div>
|
||||
<%+cbi/valuefooter%>
|
||||
@ -1,89 +0,0 @@
|
||||
<%
|
||||
if not self.embedded then
|
||||
%><form method="post" enctype="multipart/form-data" action="<%=REQUEST_URI%>"<%=
|
||||
attr("data-strings", luci.util.serialize_json({
|
||||
label = {
|
||||
choose = translate('-- Please choose --'),
|
||||
custom = translate('-- custom --'),
|
||||
},
|
||||
path = {
|
||||
resource = resource,
|
||||
browser = url("admin/filebrowser")
|
||||
}
|
||||
}))
|
||||
%>>
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="cbi.submit" value="1" /><%
|
||||
end
|
||||
|
||||
%><div class="cbi-map" id="cbi-<%=self.config%>"><%
|
||||
|
||||
if self.title and #self.title > 0 then
|
||||
%><h2 name="content"><%=self.title%></h2><%
|
||||
end
|
||||
|
||||
if self.description and #self.description > 0 then
|
||||
%><div class="cbi-map-descr"><%=self.description%></div><%
|
||||
end
|
||||
|
||||
self:render_children()
|
||||
|
||||
%></div><%
|
||||
|
||||
if self.message then
|
||||
%><div class="alert-message notice"><%=self.message%></div><%
|
||||
end
|
||||
|
||||
if self.errmessage then
|
||||
%><div class="alert-message warning"><%=self.errmessage%></div><%
|
||||
end
|
||||
|
||||
if not self.embedded then
|
||||
if type(self.hidden) == "table" then
|
||||
local k, v
|
||||
for k, v in pairs(self.hidden) do
|
||||
%><input type="hidden" id="<%=k%>" name="<%=k%>" value="<%=pcdata(v)%>" /><%
|
||||
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
|
||||
%><div class="cbi-page-actions"><%
|
||||
|
||||
if display_back then
|
||||
%><input class="cbi-button cbi-button-link" type="button" value="<%:Back to Overview%>" onclick="location.href='<%=pcdata(self.redirect)%>'" /> <%
|
||||
end
|
||||
|
||||
if display_cancel then
|
||||
local label = pcdata(self.cancel or translate("Cancel"))
|
||||
%><input class="cbi-button cbi-button-link" type="button" value="<%=label%>" onclick="cbi_submit(this, 'cbi.cancel')" /> <%
|
||||
end
|
||||
|
||||
if display_skip then
|
||||
%><input class="cbi-button cbi-button-neutral" type="button" value="<%:Skip%>" onclick="cbi_submit(this, 'cbi.skip')" /> <%
|
||||
end
|
||||
|
||||
if display_submit then
|
||||
local label = pcdata(self.submit or translate("Submit"))
|
||||
%><input class="cbi-button cbi-button-save" type="submit" value="<%=label%>" /> <%
|
||||
end
|
||||
|
||||
if display_reset then
|
||||
local label = pcdata(self.reset or translate("Reset"))
|
||||
%><input class="cbi-button cbi-button-reset" type="reset" value="<%=label%>" /> <%
|
||||
end
|
||||
|
||||
%></div><%
|
||||
end
|
||||
|
||||
%></form><%
|
||||
end
|
||||
%>
|
||||
|
||||
<script type="text/javascript">cbi_init();</script>
|
||||
@ -9,18 +9,18 @@
|
||||
</ul>
|
||||
|
||||
<script type="text/javascript">
|
||||
let re = /\/admin\/services\/docker\/container\//
|
||||
let re = /\/admin\/docker\/container\//
|
||||
let p = window.location.href
|
||||
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","file","console","logs"]
|
||||
actions.forEach(function(item) {
|
||||
document.getElementById("a-cbi-tab-container_" + item).href= path[0]+"/admin/services/docker/container/"+container_id+'/'+item
|
||||
document.getElementById("a-cbi-tab-container_" + item).href= path[0]+"/admin/docker/container/"+container_id+'/'+item
|
||||
if (action === item) {
|
||||
document.getElementById("cbi-tab-container_" + item).className="cbi-tab"
|
||||
} else {
|
||||
document.getElementById("cbi-tab-container_" + item).className="cbi-tab-disable"
|
||||
document.getElementById("cbi-tab-container_" + item).className="cbi-tab-disabled"
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
@ -3,4 +3,4 @@
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
document.getElementById("terminal").src = "http://" + window.location.hostname + ":7682";
|
||||
</script>
|
||||
</script>
|
||||
@ -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))
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
@ -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 @@
|
||||
}
|
||||
|
||||
});
|
||||
//]]></script>
|
||||
//]]></script>
|
||||
@ -1,5 +1,3 @@
|
||||
<!-- this page has no effect -->
|
||||
|
||||
<input type="text" class="cbi-input-text" name="isrc" placeholder="http://host/image.tar" id="isrc" />
|
||||
<input type="text" class="cbi-input-text" name="itag" placeholder="repository:tag" id="itag" />
|
||||
<div style="display: inline-block;">
|
||||
@ -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("<none>")) 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 @@
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -8,4 +8,4 @@
|
||||
</div>
|
||||
<% if self.title == "Events" then %>
|
||||
<%+footer%>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@ -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%>
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Command line%>" onclick="show_reslov_dialog()" />
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
<%+cbi/valuefooter%>
|
||||
@ -136,7 +136,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="pure-u-3-5">
|
||||
<h4 style="text-align: right; font-size: 1rem"><%:Containers%></h4>
|
||||
<h4 style="text-align: right;">
|
||||
<%- if self.containers_total ~= "-" then -%><a href="/cgi-bin/luci/admin/services/docker/containers"><%- end -%>
|
||||
<%- if self.containers_total ~= "-" then -%><a href="/cgi-bin/luci/admin/docker/containers"><%- end -%>
|
||||
<span style="font-size: 2rem; color: #2dce89;"><%=self.containers_running%></span>
|
||||
<span style="font-size: 1rem; color: #8898aa !important;">/<%=self.containers_total%></span>
|
||||
<%- if self.containers_total ~= "-" then -%></a><%- end -%>
|
||||
@ -160,7 +160,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="pure-u-3-5">
|
||||
<h4 style="text-align: right; font-size: 1rem"><%:Images%></h4>
|
||||
<h4 style="text-align: right;">
|
||||
<%- if self.images_total ~= "-" then -%><a href="/cgi-bin/luci/admin/services/docker/images"><%- end -%>
|
||||
<%- if self.images_total ~= "-" then -%><a href="/cgi-bin/luci/admin/docker/images"><%- end -%>
|
||||
<span style="font-size: 2rem; color: #2dce89;"><%=self.images_used%></span>
|
||||
<span style="font-size: 1rem; color: #8898aa !important;">/<%=self.images_total%></span>
|
||||
<%- if self.images_total ~= "-" then -%></a><%- end -%>
|
||||
@ -192,7 +192,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="pure-u-3-5">
|
||||
<h4 style="text-align: right; font-size: 1rem"><%:Networks%></h4>
|
||||
<h4 style="text-align: right;">
|
||||
<%- if self.networks_total ~= "-" then -%><a href="/cgi-bin/luci/admin/services/docker/networks"><%- end -%>
|
||||
<%- if self.networks_total ~= "-" then -%><a href="/cgi-bin/luci/admin/docker/networks"><%- end -%>
|
||||
<span style="font-size: 2rem; color: #2dce89;"><%=self.networks_total%></span>
|
||||
<!-- <span style="font-size: 1rem; color: #8898aa !important;">/20</span> -->
|
||||
<%- if self.networks_total ~= "-" then -%></a><%- end -%>
|
||||
@ -269,7 +269,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<div class="pure-u-3-5">
|
||||
<h4 style="text-align: right; font-size: 1rem"><%:Volumes%></h4>
|
||||
<h4 style="text-align: right;">
|
||||
<%- if self.volumes_total ~= "-" then -%><a href="/cgi-bin/luci/admin/services/docker/volumes"><%- end -%>
|
||||
<%- if self.volumes_total ~= "-" then -%><a href="/cgi-bin/luci/admin/docker/volumes"><%- end -%>
|
||||
<span style="font-size: 2rem; color: #2dce89;"><%=self.volumes_total%></span>
|
||||
<!-- <span style="font-size: 1rem; color: #8898aa !important;">/20</span> -->
|
||||
<%- if self.volumes_total ~= "-" then -%></a><%- end -%>
|
||||
@ -277,4 +277,4 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,31 +0,0 @@
|
||||
<br>
|
||||
<h2><%:Setting%></h2>
|
||||
<ul class="cbi-tabmenu">
|
||||
<% 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
|
||||
%>
|
||||
<li id=<%=id%> class=<%=class%> >
|
||||
<a onclick="this.blur(); return cbi_t_switch('overview-tab', '<%=k%>')" href=""><%=v%></a>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<script type="text/javascript">
|
||||
window.onload = function () {
|
||||
<% for k, v in pairs(self.tabs) do
|
||||
local display = k == self.default_tab and "block" or "none"
|
||||
local tid = "cbi-"..k.."-local"
|
||||
local sid = "cbi-"..k.."-local"
|
||||
local cid = "container.overview-tab." .. k
|
||||
%>
|
||||
mount_point_table = document.getElementById("<%=tid%>") || document.getElementById("<%=sid%>") || null
|
||||
if (mount_point_table) {
|
||||
mount_point_table.setAttribute("style", "display: <%=display%>;")
|
||||
mount_point_table.setAttribute("id", "<%=cid%>")
|
||||
cbi_t_add('overview-tab', '<%=k%>')
|
||||
// cbi_init();
|
||||
}
|
||||
<% end %>
|
||||
|
||||
}
|
||||
</script>
|
||||
@ -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 接口"
|
||||
@ -1,5 +0,0 @@
|
||||
config section 'local'
|
||||
option ea 'true'
|
||||
option en_wan 'false'
|
||||
option data_root '/opt/docker'
|
||||
option log_level 'warn'
|
||||
@ -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'
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
45
package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerman
Executable file
45
package/ctcgfw/luci-app-dockerman/root/etc/init.d/dockerman
Executable file
@ -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
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
Loading…
Reference in New Issue
Block a user