mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
dockerman: merge lisaac's commits (#3308)
* luci-lib-docker: merge lisaac's commits: * last commit: df1588052311069b95e3e567621cc9d125bd1b54 * luci-app-dockerman: merge lisaac's commits: * last commit: 86e354f18b0c95bc168d9266a7c1137ce4a988f0
This commit is contained in:
parent
30d8784a09
commit
ef9d5f9ec1
@ -1,11 +1,18 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-dockerman
|
||||
PKG_VERSION:=v0.2.2
|
||||
PKG_VERSION:=v0.3.0
|
||||
PKG_RELEASE:=beta
|
||||
PKG_MAINTAINER:=lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_LICENSE:=AGPL-3.0
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/lisaac/luci-app-dockerman.git
|
||||
PKG_SOURCE_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_SUBDIR)-$(PKG_VERSION).tar.gz
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
@ -23,6 +30,7 @@ define Package/$(PKG_NAME)/description
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
tar -xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(BUILD_DIR)
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
@ -34,12 +42,16 @@ rm -fr /tmp/luci-indexcache /tmp/luci-modulecache
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci
|
||||
cp -pR ./luasrc/* $(1)/usr/lib/lua/luci
|
||||
$(INSTALL_DIR) $(1)/
|
||||
cp -pR ./root/* $(1)/
|
||||
cp -pR $(PKG_BUILD_DIR)/root/* $(1)/
|
||||
# $(INSTALL_DIR) $(1)/www
|
||||
# cp -pR $(PKG_BUILD_DIR)/htdoc/* $(1)/www
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci
|
||||
cp -pR $(PKG_BUILD_DIR)/luasrc/* $(1)/usr/lib/lua/luci/
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
|
||||
po2lmo ./po/zh-cn/dockerman.po $(1)/usr/lib/lua/luci/i18n/dockerman.zh-cn.lmo
|
||||
$(foreach po, $(shell find $(PKG_BUILD_DIR)/po/*/*.po),\
|
||||
po2lmo $(po) $(1)/usr/lib/lua/luci/i18n/dockerman.$(shell echo $(po) | awk -F'/' '{print $$(NF-1)}').lmo;)
|
||||
#po2lmo $(PKG_BUILD_DIR)/po/zh-cn/dockerman.po $(1)/usr/lib/lua/luci/i18n/dockerman.zh-cn.lmo
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
|
@ -11,20 +11,22 @@ module("luci.controller.dockerman",package.seeall)
|
||||
function index()
|
||||
|
||||
entry({"admin", "services","docker"}, firstchild(), "Docker", 40).dependent = false
|
||||
entry({"admin","services","docker","overview"},cbi("docker/overview"),_("Overview"),0).leaf=true
|
||||
entry({"admin","services","docker","overview"},cbi("dockerman/overview"),_("Overview"),0).leaf=true
|
||||
|
||||
local socket = luci.model.uci.cursor():get("docker", "local", "socket_path")
|
||||
local socket = luci.model.uci.cursor():get("dockerman", "local", "socket_path")
|
||||
if not nixio.fs.access(socket) then return end
|
||||
if (require "luci.model.docker").new():_ping().code ~= 200 then return end
|
||||
entry({"admin","services","docker","containers"},form("docker/containers"),_("Containers"),1).leaf=true
|
||||
entry({"admin","services","docker","images"},form("docker/images"),_("Images"),2).leaf=true
|
||||
entry({"admin","services","docker","networks"},form("docker/networks"),_("Networks"),3).leaf=true
|
||||
entry({"admin","services","docker","volumes"},form("docker/volumes"),_("Volumes"),4).leaf=true
|
||||
entry({"admin","services","docker","containers"},form("dockerman/containers"),_("Containers"),1).leaf=true
|
||||
entry({"admin","services","docker","images"},form("dockerman/images"),_("Images"),2).leaf=true
|
||||
entry({"admin","services","docker","networks"},form("dockerman/networks"),_("Networks"),3).leaf=true
|
||||
entry({"admin","services","docker","volumes"},form("dockerman/volumes"),_("Volumes"),4).leaf=true
|
||||
entry({"admin","services","docker","events"},call("action_events"),_("Events"),5)
|
||||
entry({"admin","services","docker","newcontainer"},form("docker/newcontainer")).leaf=true
|
||||
entry({"admin","services","docker","newnetwork"},form("docker/newnetwork")).leaf=true
|
||||
entry({"admin","services","docker","container"},form("docker/container")).leaf=true
|
||||
entry({"admin","services","docker","newcontainer"},form("dockerman/newcontainer")).leaf=true
|
||||
entry({"admin","services","docker","newnetwork"},form("dockerman/newnetwork")).leaf=true
|
||||
entry({"admin","services","docker","container"},form("dockerman/container")).leaf=true
|
||||
entry({"admin","services","docker","container_stats"},call("action_get_container_stats")).leaf=true
|
||||
entry({"admin","services","docker","container_get_archive"},call("download_archive")).leaf=true
|
||||
entry({"admin","services","docker","container_put_archive"},call("upload_archive")).leaf=true
|
||||
entry({"admin","services","docker","confirm"},call("action_confirm")).leaf=true
|
||||
|
||||
end
|
||||
@ -35,7 +37,7 @@ function action_events()
|
||||
local dk = docker.new()
|
||||
local query ={}
|
||||
query["until"] = os.time()
|
||||
local events = dk:events(nil, query)
|
||||
local events = dk:events({query = query})
|
||||
for _, v in ipairs(events.body) do
|
||||
if v.Type == "container" then
|
||||
logs = (logs ~= "" and (logs .. "\n") or logs) .. "[" .. os.date("%Y-%m-%d %H:%M:%S", v.time) .."] "..v.Type.. " " .. (v.Action or "null") .. " Container ID:".. (v.Actor.ID or "null") .. " Container Name:" .. (v.Actor.Attributes.name or "null")
|
||||
@ -45,7 +47,7 @@ function action_events()
|
||||
logs = (logs ~= "" and (logs .. "\n") or logs) .. "[" .. os.date("%Y-%m-%d %H:%M:%S", v.time) .."] "..v.Type.. " " .. v.Action .. " Image:".. (v.Actor.ID or "null").. " Image Name:" .. (v.Actor.Attributes.name or "null")
|
||||
end
|
||||
end
|
||||
luci.template.render("docker/logs", {self={syslog = logs, title="Docker Events"}})
|
||||
luci.template.render("dockerman/logs", {self={syslog = logs, title="Docker Events"}})
|
||||
end
|
||||
|
||||
local calculate_cpu_percent = function(d)
|
||||
@ -94,9 +96,9 @@ end
|
||||
function action_get_container_stats(container_id)
|
||||
if container_id then
|
||||
local dk = docker.new()
|
||||
local response = dk.containers:inspect(container_id)
|
||||
local response = dk.containers:inspect({id = container_id})
|
||||
if response.code == 200 and response.body.State.Running then
|
||||
response = dk.containers:stats(container_id, {stream=false})
|
||||
response = dk.containers:stats({id = container_id, query = {stream = false}})
|
||||
if response.code == 200 then
|
||||
local container_stats = response.body
|
||||
local cpu_percent = calculate_cpu_percent(container_stats)
|
||||
@ -136,7 +138,7 @@ function action_get_container_stats(container_id)
|
||||
end
|
||||
|
||||
function action_confirm()
|
||||
local status_path=luci.model.uci.cursor():get("docker", "local", "status_path")
|
||||
local status_path=luci.model.uci.cursor():get("dockerman", "local", "status_path")
|
||||
local data = nixio.fs.readfile(status_path)
|
||||
if data then
|
||||
code = 202
|
||||
@ -151,3 +153,49 @@ function action_confirm()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({info = data})
|
||||
end
|
||||
|
||||
function download_archive()
|
||||
local id = luci.http.formvalue("id")
|
||||
local path = luci.http.formvalue("path")
|
||||
local dk = docker.new()
|
||||
local first
|
||||
|
||||
local cb = function(res, chunk)
|
||||
if res.code == 200 then
|
||||
if not first then
|
||||
first = true
|
||||
luci.http.header('Content-Disposition', 'inline; filename="archive.tar"')
|
||||
luci.http.header('Content-Type', 'application\/x-tar')
|
||||
end
|
||||
luci.ltn12.pump.all(chunk, luci.http.write)
|
||||
else
|
||||
if not first then
|
||||
first = true
|
||||
luci.http.prepare_content("text/plain")
|
||||
end
|
||||
luci.ltn12.pump.all(chunk, luci.http.write)
|
||||
end
|
||||
end
|
||||
|
||||
local res = dk.containers:get_archive({id = id, query = {path = path}}, cb)
|
||||
end
|
||||
|
||||
function upload_archive(container_id)
|
||||
local path = luci.http.formvalue("upload-path")
|
||||
local dk = docker.new()
|
||||
local ltn12 = require "luci.ltn12"
|
||||
|
||||
rec_send = function(sinkout)
|
||||
luci.http.setfilehandler(function (meta, chunk, eof)
|
||||
if chunk then
|
||||
ltn12.pump.step(ltn12.source.string(chunk), sinkout)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local res = dk.containers:put_archive({id = container_id, query = {path = path}, body = rec_send})
|
||||
local msg = res and res.body and res.body.message or nil
|
||||
luci.http.status(res.code, msg)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({message = msg})
|
||||
end
|
||||
|
@ -12,7 +12,7 @@ local action = arg[2] or "info"
|
||||
|
||||
local images, networks, containers_info
|
||||
if not container_id then return end
|
||||
local res = dk.containers:inspect(container_id)
|
||||
local res = dk.containers:inspect({id = container_id})
|
||||
if res.code < 300 then container_info = res.body else return end
|
||||
res = dk.networks:list()
|
||||
if res.code < 300 then networks = res.body else return end
|
||||
@ -110,9 +110,9 @@ local start_stop_remove = function(m, cmd)
|
||||
docker:append_status("Containers: " .. cmd .. " " .. container_id .. "...")
|
||||
local res
|
||||
if cmd ~= "upgrade" then
|
||||
res = dk.containers[cmd](dk, container_id)
|
||||
res = dk.containers[cmd](dk, {id = container_id})
|
||||
else
|
||||
res = dk.containers_upgrade(dk, container_id)
|
||||
res = dk.containers_upgrade(dk, {id = container_id})
|
||||
end
|
||||
if res and res.code >= 300 then
|
||||
docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message))
|
||||
@ -128,11 +128,11 @@ local start_stop_remove = function(m, cmd)
|
||||
end
|
||||
|
||||
m=SimpleForm("docker", container_info.Name:sub(2), translate("Docker Container") )
|
||||
m.template = "docker/cbi/xsimpleform"
|
||||
m.template = "dockerman/cbi/xsimpleform"
|
||||
m.redirect = luci.dispatcher.build_url("admin/services/docker/containers")
|
||||
-- m:append(Template("docker/container"))
|
||||
-- m:append(Template("dockerman/container"))
|
||||
docker_status = m:section(SimpleSection)
|
||||
docker_status.template="docker/apply_widget"
|
||||
docker_status.template = "dockerman/apply_widget"
|
||||
docker_status.err=nixio.fs.readfile(dk.options.status_path)
|
||||
-- luci.util.perror(docker_status.err)
|
||||
if docker_status.err then docker:clear_status() end
|
||||
@ -141,35 +141,35 @@ if docker_status.err then docker:clear_status() end
|
||||
action_section = m:section(Table,{{}})
|
||||
action_section.notitle=true
|
||||
action_section.rowcolors=false
|
||||
action_section.template="cbi/nullsection"
|
||||
action_section.template = "cbi/nullsection"
|
||||
|
||||
btnstart=action_section:option(Button, "_start")
|
||||
btnstart.template="docker/cbi/inlinebutton"
|
||||
btnstart.template = "dockerman/cbi/inlinebutton"
|
||||
btnstart.inputtitle=translate("Start")
|
||||
btnstart.inputstyle = "apply"
|
||||
btnstart.forcewrite = true
|
||||
btnrestart=action_section:option(Button, "_restart")
|
||||
btnrestart.template="docker/cbi/inlinebutton"
|
||||
btnrestart.template = "dockerman/cbi/inlinebutton"
|
||||
btnrestart.inputtitle=translate("Restart")
|
||||
btnrestart.inputstyle = "reload"
|
||||
btnrestart.forcewrite = true
|
||||
btnstop=action_section:option(Button, "_stop")
|
||||
btnstop.template="docker/cbi/inlinebutton"
|
||||
btnstop.template = "dockerman/cbi/inlinebutton"
|
||||
btnstop.inputtitle=translate("Stop")
|
||||
btnstop.inputstyle = "reset"
|
||||
btnstop.forcewrite = true
|
||||
btnupgrade=action_section:option(Button, "_upgrade")
|
||||
btnupgrade.template="docker/cbi/inlinebutton"
|
||||
btnupgrade.template = "dockerman/cbi/inlinebutton"
|
||||
btnupgrade.inputtitle=translate("Upgrade")
|
||||
btnupgrade.inputstyle = "reload"
|
||||
btnstop.forcewrite = true
|
||||
btnduplicate=action_section:option(Button, "_duplicate")
|
||||
btnduplicate.template="docker/cbi/inlinebutton"
|
||||
btnduplicate.template = "dockerman/cbi/inlinebutton"
|
||||
btnduplicate.inputtitle=translate("Duplicate")
|
||||
btnduplicate.inputstyle = "add"
|
||||
btnstop.forcewrite = true
|
||||
btnremove=action_section:option(Button, "_remove")
|
||||
btnremove.template="docker/cbi/inlinebutton"
|
||||
btnremove.template = "dockerman/cbi/inlinebutton"
|
||||
btnremove.inputtitle=translate("Remove")
|
||||
btnremove.inputstyle = "remove"
|
||||
btnremove.forcewrite = true
|
||||
@ -194,7 +194,7 @@ btnduplicate.write = function(self, section)
|
||||
end
|
||||
|
||||
tab_section = m:section(SimpleSection)
|
||||
tab_section.template="docker/container"
|
||||
tab_section.template = "dockerman/container"
|
||||
|
||||
if action == "info" then
|
||||
m.submit = false
|
||||
@ -302,7 +302,7 @@ if action == "info" then
|
||||
end
|
||||
dv_opts.render = function(self, section, scope)
|
||||
if table_info[section]._key==translate("Connect Network") then
|
||||
self.template="cbi/value"
|
||||
self.template = "cbi/value"
|
||||
self.keylist = {}
|
||||
self.vallist = {}
|
||||
self.placeholder = "10.1.1.254"
|
||||
@ -324,7 +324,7 @@ if action == "info" then
|
||||
self.template = "cbi/button"
|
||||
Button.render(self, section, scope)
|
||||
else
|
||||
self.template = "docker/cbi/dummyvalue"
|
||||
self.template = "dockerman/cbi/dummyvalue"
|
||||
self.default=""
|
||||
DummyValue.render(self, section, scope)
|
||||
end
|
||||
@ -336,16 +336,16 @@ if action == "info" then
|
||||
if section == "01name" then
|
||||
docker:append_status("Containers: rename " .. container_id .. "...")
|
||||
local new_name = table_info[section]._value
|
||||
res = dk.containers:rename(container_id,{name=new_name})
|
||||
res = dk.containers:rename({id = container_id, query = {name=new_name}})
|
||||
elseif section == "08restart" then
|
||||
docker:append_status("Containers: update " .. container_id .. "...")
|
||||
local new_restart = table_info[section]._value
|
||||
res = dk.containers:update(container_id, nil, {RestartPolicy = {Name = new_restart}})
|
||||
res = dk.containers:update({id = container_id, body = {RestartPolicy = {Name = new_restart}}})
|
||||
elseif table_info[section]._key == translate("Network") then
|
||||
local _,_,leave_network = table_info[section]._value:find("(.-) | .+")
|
||||
leave_network = leave_network or table_info[section]._value
|
||||
docker:append_status("Network: disconnect " .. leave_network .. container_id .. "...")
|
||||
res = dk.networks:disconnect(leave_network, nil, {Container = container_id})
|
||||
res = dk.networks:disconnect({name = leave_network, body = {Container = container_id}})
|
||||
elseif section == "15connect" then
|
||||
local connect_network = table_info[section]._value
|
||||
local network_opiton
|
||||
@ -358,7 +358,7 @@ if action == "info" then
|
||||
} or nil
|
||||
end
|
||||
docker:append_status("Network: connect " .. connect_network .. container_id .. "...")
|
||||
res = dk.networks:connect(connect_network, nil, {Container = container_id, EndpointConfig= network_opiton})
|
||||
res = dk.networks:connect({name = connect_network, body = {Container = container_id, EndpointConfig= network_opiton}})
|
||||
end
|
||||
if res and res.code > 300 then
|
||||
docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message))
|
||||
@ -370,7 +370,7 @@ if action == "info" then
|
||||
|
||||
-- info end
|
||||
elseif action == "edit" then
|
||||
editsection= m:section(SimpleSection)
|
||||
local editsection= m:section(SimpleSection)
|
||||
d = editsection:option( Value, "cpus", translate("CPUs"), translate("Number of CPUs. Number is a fractional number. 0.000 means no limit."))
|
||||
d.placeholder = "1.5"
|
||||
d.rmempty = true
|
||||
@ -420,7 +420,7 @@ elseif action == "edit" then
|
||||
}
|
||||
docker:clear_status()
|
||||
docker:append_status("Containers: update " .. container_id .. "...")
|
||||
local res = dk.containers:update(container_id, nil, request_body)
|
||||
local res = dk.containers:update({id = container_id, body = request_body})
|
||||
if res and res.code >= 300 then
|
||||
docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message))
|
||||
else
|
||||
@ -429,31 +429,37 @@ elseif action == "edit" then
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/container/"..container_id.."/edit"))
|
||||
end
|
||||
end
|
||||
elseif action == "file" then
|
||||
local filesection= m:section(SimpleSection)
|
||||
m.submit = false
|
||||
m.reset = false
|
||||
filesection.template = "dockerman/container_file"
|
||||
filesection.container = container_id
|
||||
elseif action == "logs" then
|
||||
logsection= m:section(SimpleSection)
|
||||
local logsection= m:section(SimpleSection)
|
||||
local logs = ""
|
||||
local query ={
|
||||
stdout = 1,
|
||||
stderr = 1,
|
||||
tail = 1000
|
||||
}
|
||||
local logs = dk.containers:logs(container_id, query)
|
||||
local logs = dk.containers:logs({id = container_id, query = query})
|
||||
if logs.code == 200 then
|
||||
logsection.syslog=logs.body
|
||||
else
|
||||
logsection.syslog="Get Logs ERROR\n"..logs.code..": "..logs.body
|
||||
end
|
||||
logsection.title=translate("Container Logs")
|
||||
logsection.template="docker/logs"
|
||||
logsection.template = "dockerman/logs"
|
||||
m.submit = false
|
||||
m.reset = false
|
||||
m.reset = false
|
||||
elseif action == "stats" then
|
||||
local response = dk.containers:top(container_id, {ps_args="-aux"})
|
||||
local response = dk.containers:top({id = container_id, query = {ps_args="-aux"}})
|
||||
local container_top
|
||||
if response.code == 200 then
|
||||
container_top=response.body
|
||||
else
|
||||
response = dk.containers:top(container_id)
|
||||
response = dk.containers:top({id = container_id})
|
||||
if response.code == 200 then
|
||||
container_top=response.body
|
||||
end
|
||||
@ -463,7 +469,7 @@ elseif action == "stats" then
|
||||
container_top=response.body
|
||||
stat_section = m:section(SimpleSection)
|
||||
stat_section.container_id = container_id
|
||||
stat_section.template="docker/stats"
|
||||
stat_section.template = "dockerman/stats"
|
||||
table_stats = {cpu={key=translate("CPU Useage"),value='-'},memory={key=translate("Memory Useage"),value='-'}}
|
||||
stat_section = m:section(Table, table_stats, translate("Stats"))
|
||||
stat_section:option(DummyValue, "key", translate("Stats")).width="33%"
|
@ -14,7 +14,7 @@ local res = dk.images:list()
|
||||
if res.code <300 then images = res.body else return end
|
||||
res = dk.networks:list()
|
||||
if res.code <300 then networks = res.body else return end
|
||||
res = dk.containers:list(nil, {all=true})
|
||||
res = dk.containers:list({query = {all=true}})
|
||||
if res.code <300 then containers = res.body else return end
|
||||
|
||||
local urlencode = luci.http.protocol and luci.http.protocol.urlencode or luci.util.urlencode
|
||||
@ -68,12 +68,12 @@ local c_lists = get_containers()
|
||||
-- list Containers
|
||||
-- m = Map("docker", translate("Docker"))
|
||||
m = SimpleForm("docker", translate("Docker"))
|
||||
m.template = "docker/cbi/xsimpleform"
|
||||
m.template = "dockerman/cbi/xsimpleform"
|
||||
m.submit=false
|
||||
m.reset=false
|
||||
|
||||
docker_status = m:section(SimpleSection)
|
||||
docker_status.template="docker/apply_widget"
|
||||
docker_status.template = "dockerman/apply_widget"
|
||||
docker_status.err=nixio.fs.readfile(dk.options.status_path)
|
||||
-- luci.util.perror(docker_status.err)
|
||||
if docker_status.err then docker:clear_status() end
|
||||
@ -91,7 +91,7 @@ container_id = c_table:option(DummyValue, "_id", translate("ID"))
|
||||
container_id.width="10%"
|
||||
container_name = c_table:option(DummyValue, "_name", translate("Container Name"))
|
||||
container_name.width="20%"
|
||||
container_name.template="docker/cbi/dummyvalue"
|
||||
container_name.template = "dockerman/cbi/dummyvalue"
|
||||
container_name.href = function (self, section)
|
||||
return luci.dispatcher.build_url("admin/services/docker/container/" .. urlencode(container_id:cfgvalue(section)))
|
||||
end
|
||||
@ -103,7 +103,7 @@ container_ip.width="15%"
|
||||
container_ports = c_table:option(DummyValue, "_ports", translate("Ports"))
|
||||
container_ports.width="10%"
|
||||
container_image = c_table:option(DummyValue, "_image", translate("Image"))
|
||||
container_image.template="docker/cbi/dummyvalue"
|
||||
container_image.template = "dockerman/cbi/dummyvalue"
|
||||
container_image.width="10%"
|
||||
-- container_image.href = function (self, section)
|
||||
-- return luci.dispatcher.build_url("admin/services/docker/image/" .. urlencode(c_lists[section]._image_id))
|
||||
@ -131,12 +131,11 @@ local start_stop_remove = function(m,cmd)
|
||||
end
|
||||
end
|
||||
if #c_selected >0 then
|
||||
-- luci.util.perror(dk.options.status_path)
|
||||
docker:clear_status()
|
||||
local success = true
|
||||
for _,cont in ipairs(c_selected) do
|
||||
docker:append_status("Containers: " .. cmd .. " " .. cont .. "...")
|
||||
local res = dk.containers[cmd](dk, cont)
|
||||
local res = dk.containers[cmd](dk, {id = cont})
|
||||
if res and res.code >= 300 then
|
||||
success = false
|
||||
docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "<br>")
|
||||
@ -156,26 +155,26 @@ action_section.template="cbi/nullsection"
|
||||
|
||||
btnnew=action_section:option(Button, "_new")
|
||||
btnnew.inputtitle= translate("New")
|
||||
btnnew.template="docker/cbi/inlinebutton"
|
||||
btnnew.template = "dockerman/cbi/inlinebutton"
|
||||
btnnew.inputstyle = "add"
|
||||
btnnew.forcewrite = true
|
||||
btnstart=action_section:option(Button, "_start")
|
||||
btnstart.template="docker/cbi/inlinebutton"
|
||||
btnstart.template = "dockerman/cbi/inlinebutton"
|
||||
btnstart.inputtitle=translate("Start")
|
||||
btnstart.inputstyle = "apply"
|
||||
btnstart.forcewrite = true
|
||||
btnrestart=action_section:option(Button, "_restart")
|
||||
btnrestart.template="docker/cbi/inlinebutton"
|
||||
btnrestart.template = "dockerman/cbi/inlinebutton"
|
||||
btnrestart.inputtitle=translate("Restart")
|
||||
btnrestart.inputstyle = "reload"
|
||||
btnrestart.forcewrite = true
|
||||
btnstop=action_section:option(Button, "_stop")
|
||||
btnstop.template="docker/cbi/inlinebutton"
|
||||
btnstop.template = "dockerman/cbi/inlinebutton"
|
||||
btnstop.inputtitle=translate("Stop")
|
||||
btnstop.inputstyle = "reset"
|
||||
btnstop.forcewrite = true
|
||||
btnremove=action_section:option(Button, "_remove")
|
||||
btnremove.template="docker/cbi/inlinebutton"
|
||||
btnremove.template = "dockerman/cbi/inlinebutton"
|
||||
btnremove.inputtitle=translate("Remove")
|
||||
btnremove.inputstyle = "remove"
|
||||
btnremove.forcewrite = true
|
@ -11,7 +11,7 @@ local dk = docker.new()
|
||||
local containers, images
|
||||
local res = dk.images:list()
|
||||
if res.code <300 then images = res.body else return end
|
||||
res = dk.containers:list(nil, {all=true})
|
||||
res = dk.containers:list({query = {all=true}})
|
||||
if res.code <300 then containers = res.body else return end
|
||||
|
||||
function get_images()
|
||||
@ -45,7 +45,7 @@ local image_list = get_images()
|
||||
|
||||
-- m = Map("docker", translate("Docker"))
|
||||
m = SimpleForm("docker", translate("Docker"))
|
||||
m.template = "docker/cbi/xsimpleform"
|
||||
m.template = "dockerman/cbi/xsimpleform"
|
||||
m.submit=false
|
||||
m.reset=false
|
||||
|
||||
@ -53,14 +53,17 @@ local pull_value={{_image_tag_name="", _registry="index.docker.io"}}
|
||||
local pull_section = m:section(Table,pull_value, translate("Pull Image"))
|
||||
pull_section.template="cbi/nullsection"
|
||||
local tag_name = pull_section:option(Value, "_image_tag_name")
|
||||
tag_name.template="docker/cbi/inlinevalue"
|
||||
tag_name.template = "dockerman/cbi/inlinevalue"
|
||||
tag_name.placeholder="hello-world:latest"
|
||||
local registry = pull_section:option(Value, "_registry")
|
||||
registry.template="docker/cbi/inlinevalue"
|
||||
registry:value("index.docker.io", "DockerHub")
|
||||
registry.template = "dockerman/cbi/inlinevalue"
|
||||
registry:value("index.docker.io", "Docker Hub")
|
||||
registry:value("hub-mirror.c.163.com", "163 Mirror")
|
||||
registry:value("mirror.ccs.tencentyun.com", "Tencent Mirror")
|
||||
registry:value("docker.mirrors.ustc.edu.cn", "USTC Mirror")
|
||||
local action_pull = pull_section:option(Button, "_pull")
|
||||
action_pull.inputtitle= translate("Pull")
|
||||
action_pull.template="docker/cbi/inlinebutton"
|
||||
action_pull.template = "dockerman/cbi/inlinebutton"
|
||||
action_pull.inputstyle = "add"
|
||||
tag_name.write = function(self, section,value)
|
||||
local hastag = value:find(":")
|
||||
@ -80,19 +83,21 @@ action_pull.write = function(self, section)
|
||||
if not tmp then
|
||||
_,_,server = server:find("([%.%w%-%_]+)")
|
||||
end
|
||||
local json_stringify = luci.json and luci.json.encode or luci.jsonc.stringify
|
||||
if tag then
|
||||
local json_stringify = luci.jsonc and luci.jsonc.stringify
|
||||
if tag and tag ~= "" then
|
||||
docker:clear_status()
|
||||
docker:append_status("Images: " .. "pulling" .. " " .. tag .. "...")
|
||||
local x_auth = nixio.bin.b64encode(json_stringify({serveraddress= server}))
|
||||
local res = dk.images:create(nil, {fromImage=tag,_header={["X-Registry-Auth"]=x_auth}})
|
||||
local res = dk.images:create({query = {fromImage=tag}, header={["X-Registry-Auth"] = x_auth}})
|
||||
if res and res.code >=300 then
|
||||
docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "<br>")
|
||||
else
|
||||
docker:append_status("done<br>")
|
||||
end
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/images"))
|
||||
else
|
||||
docker:append_status("fail code: 400 please input the name of image name!")
|
||||
end
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/images"))
|
||||
end
|
||||
|
||||
image_table = m:section(Table, image_list, translate("Images"))
|
||||
@ -126,11 +131,9 @@ local remove_action = function(force)
|
||||
docker:clear_status()
|
||||
for _,img in ipairs(image_selected) do
|
||||
docker:append_status("Images: " .. "remove" .. " " .. img .. "...")
|
||||
local query_body ={}
|
||||
if force then
|
||||
query_body.force = true
|
||||
end
|
||||
local msg = dk.images["remove"](dk, img, query_body)
|
||||
local query
|
||||
if force then query = {force = true} end
|
||||
local msg = dk.images:remove({id = img, query = query})
|
||||
if msg.code ~= 200 then
|
||||
docker:append_status("fail code:" .. msg.code.." ".. (msg.body.message and msg.body.message or msg.message).. "<br>")
|
||||
success = false
|
||||
@ -144,7 +147,7 @@ local remove_action = function(force)
|
||||
end
|
||||
|
||||
docker_status = m:section(SimpleSection)
|
||||
docker_status.template="docker/apply_widget"
|
||||
docker_status.template = "dockerman/apply_widget"
|
||||
docker_status.err=nixio.fs.readfile(dk.options.status_path)
|
||||
if docker_status.err then docker:clear_status() end
|
||||
|
||||
@ -155,7 +158,7 @@ action.template="cbi/nullsection"
|
||||
|
||||
btnremove = action:option(Button, "remove")
|
||||
btnremove.inputtitle= translate("Remove")
|
||||
btnremove.template="docker/cbi/inlinebutton"
|
||||
btnremove.template = "dockerman/cbi/inlinebutton"
|
||||
btnremove.inputstyle = "remove"
|
||||
btnremove.forcewrite = true
|
||||
btnremove.write = function(self, section)
|
||||
@ -164,7 +167,7 @@ end
|
||||
|
||||
btnforceremove = action:option(Button, "forceremove")
|
||||
btnforceremove.inputtitle= translate("Force Remove")
|
||||
btnforceremove.template="docker/cbi/inlinebutton"
|
||||
btnforceremove.template = "dockerman/cbi/inlinebutton"
|
||||
btnforceremove.inputstyle = "remove"
|
||||
btnforceremove.forcewrite = true
|
||||
btnforceremove.write = function(self, section)
|
@ -36,7 +36,7 @@ end
|
||||
local network_list = get_networks()
|
||||
-- m = Map("docker", translate("Docker"))
|
||||
m = SimpleForm("docker", translate("Docker"))
|
||||
m.template = "docker/cbi/xsimpleform"
|
||||
m.template = "dockerman/cbi/xsimpleform"
|
||||
m.submit=false
|
||||
m.reset=false
|
||||
|
||||
@ -44,7 +44,7 @@ network_table = m:section(Table, network_list, translate("Networks"))
|
||||
network_table.nodescr=true
|
||||
|
||||
network_selecter = network_table:option(Flag, "_selected","")
|
||||
network_selecter.template = "docker/cbi/xfvalue"
|
||||
network_selecter.template = "dockerman/cbi/xfvalue"
|
||||
network_id = network_table:option(DummyValue, "_id", translate("ID"))
|
||||
network_selecter.disabled = 0
|
||||
network_selecter.enabled = 1
|
||||
@ -68,7 +68,7 @@ network_selecter.write = function(self, section, value)
|
||||
end
|
||||
|
||||
docker_status = m:section(SimpleSection)
|
||||
docker_status.template="docker/apply_widget"
|
||||
docker_status.template = "dockerman/apply_widget"
|
||||
docker_status.err=nixio.fs.readfile(dk.options.status_path)
|
||||
if docker_status.err then docker:clear_status() end
|
||||
|
||||
@ -78,7 +78,7 @@ action.rowcolors=false
|
||||
action.template="cbi/nullsection"
|
||||
btnnew=action:option(Button, "_new")
|
||||
btnnew.inputtitle= translate("New")
|
||||
btnnew.template="docker/cbi/inlinebutton"
|
||||
btnnew.template = "dockerman/cbi/inlinebutton"
|
||||
btnnew.notitle=true
|
||||
btnnew.inputstyle = "add"
|
||||
btnnew.forcewrite = true
|
||||
@ -87,7 +87,7 @@ btnnew.write = function(self, section)
|
||||
end
|
||||
btnremove = action:option(Button, "_remove")
|
||||
btnremove.inputtitle= translate("Remove")
|
||||
btnremove.template="docker/cbi/inlinebutton"
|
||||
btnremove.template = "dockerman/cbi/inlinebutton"
|
||||
btnremove.inputstyle = "remove"
|
||||
btnremove.forcewrite = true
|
||||
btnremove.write = function(self, section)
|
||||
@ -105,7 +105,7 @@ btnremove.write = function(self, section)
|
||||
docker:clear_status()
|
||||
for _,net in ipairs(network_selected) do
|
||||
docker:append_status("Networks: " .. "remove" .. " " .. net .. "...")
|
||||
local res = dk.networks["remove"](dk, net)
|
||||
local res = dk.networks["remove"](dk, {id = net})
|
||||
if res and res.code >= 300 then
|
||||
docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "<br>")
|
||||
success = false
|
@ -13,7 +13,7 @@ local create_body = {}
|
||||
|
||||
local images = dk.images:list().body
|
||||
local networks = dk.networks:list().body
|
||||
local containers = dk.containers:list(nil, {all=true}).body
|
||||
local containers = dk.containers:list({query = {all=true}}).body
|
||||
|
||||
local is_quot_complete = function(str)
|
||||
if not str then return true end
|
||||
@ -158,7 +158,7 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
end
|
||||
elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then
|
||||
local container_id = cmd_line:match("^duplicate/(.+)")
|
||||
create_body = dk:containers_duplicate_config(container_id)
|
||||
create_body = dk:containers_duplicate_config({id = container_id})
|
||||
if not create_body.HostConfig then create_body.HostConfig = {} end
|
||||
if next(create_body) ~= nil then
|
||||
default_config.name = nil
|
||||
@ -204,14 +204,14 @@ elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then
|
||||
end
|
||||
|
||||
local m = SimpleForm("docker", translate("Docker"))
|
||||
m.template = "docker/cbi/xsimpleform"
|
||||
m.template = "dockerman/cbi/xsimpleform"
|
||||
m.redirect = luci.dispatcher.build_url("admin", "services","docker", "containers")
|
||||
-- m.reset = false
|
||||
-- m.submit = false
|
||||
-- new Container
|
||||
|
||||
docker_status = m:section(SimpleSection)
|
||||
docker_status.template="docker/apply_widget"
|
||||
docker_status.template = "dockerman/apply_widget"
|
||||
docker_status.err=nixio.fs.readfile(dk.options.status_path)
|
||||
if docker_status.err then docker:clear_status() end
|
||||
|
||||
@ -221,7 +221,7 @@ s.anonymous = true
|
||||
|
||||
local d = s:option(DummyValue,"cmd_line", translate("Resolv CLI"))
|
||||
d.rawhtml = true
|
||||
d.template = "docker/resolv_container"
|
||||
d.template = "dockerman/resolv_container"
|
||||
|
||||
d = s:option(Value, "name", translate("Container Name"))
|
||||
d.rmempty = true
|
||||
@ -279,14 +279,14 @@ d_ip:depends("network", "nil")
|
||||
d_ip.default = default_config.ip or nil
|
||||
|
||||
d = s:option(DynamicList, "link", translate("Links with other containers"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.template = "dockerman/cbi/xdynlist"
|
||||
d.placeholder = "container_name:alias"
|
||||
d.rmempty = true
|
||||
d:depends("network", "bridge")
|
||||
d.default = default_config.link or nil
|
||||
|
||||
d = s:option(DynamicList, "dns", translate("Set custom DNS servers"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.template = "dockerman/cbi/xdynlist"
|
||||
d.placeholder = "8.8.8.8"
|
||||
d.rmempty = true
|
||||
d.default = default_config.dns or nil
|
||||
@ -297,19 +297,19 @@ d.rmempty = true
|
||||
d.default = default_config.user or nil
|
||||
|
||||
d = s:option(DynamicList, "env", translate("Environmental Variable(-e)"), translate("Set environment variables to inside the container"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.template = "dockerman/cbi/xdynlist"
|
||||
d.placeholder = "TZ=Asia/Shanghai"
|
||||
d.rmempty = true
|
||||
d.default = default_config.env or nil
|
||||
|
||||
d = s:option(DynamicList, "mount", translate("Bind Mount(-v)"), translate("Bind mount a volume"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.template = "dockerman/cbi/xdynlist"
|
||||
d.placeholder = "/media:/media:slave"
|
||||
d.rmempty = true
|
||||
d.default = default_config.mount or nil
|
||||
|
||||
local d_ports = s:option(DynamicList, "port", translate("Exposed Ports(-p)"), translate("Publish container's port(s) to the host"))
|
||||
d_ports.template = "docker/cbi/xdynlist"
|
||||
d_ports.template = "dockerman/cbi/xdynlist"
|
||||
d_ports.placeholder = "2200:22/tcp"
|
||||
d_ports.rmempty = true
|
||||
d_ports.default = default_config.port or nil
|
||||
@ -325,20 +325,20 @@ d.disabled = 0
|
||||
d.enabled = 1
|
||||
d.default = default_config.advance or 0
|
||||
|
||||
d = s:option(Value, "hostname", translate("Host Name"))
|
||||
d = s:option(Value, "hostname", translate("Host Name"), translate("The hostname to use for the container"))
|
||||
d.rmempty = true
|
||||
d.default = default_config.hostname or nil
|
||||
d:depends("advance", 1)
|
||||
|
||||
d = s:option(DynamicList, "device", translate("Device(--device)"), translate("Add host device to the container"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.template = "dockerman/cbi/xdynlist"
|
||||
d.placeholder = "/dev/sda:/dev/xvdc:rwm"
|
||||
d.rmempty = true
|
||||
d:depends("advance", 1)
|
||||
d.default = default_config.device or nil
|
||||
|
||||
d = s:option(DynamicList, "tmpfs", translate("Tmpfs(--tmpfs)"), translate("Mount tmpfs directory"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.template = "dockerman/cbi/xdynlist"
|
||||
d.placeholder = "/run:rw,noexec,nosuid,size=65536k"
|
||||
d.rmempty = true
|
||||
d:depends("advance", 1)
|
||||
@ -538,10 +538,10 @@ m.handle = function(self, state, data)
|
||||
end
|
||||
local pull_image = function(image)
|
||||
local server = "index.docker.io"
|
||||
local json_stringify = luci.json and luci.json.encode or luci.jsonc.stringify
|
||||
local json_stringify = luci.jsonc and luci.jsonc.stringify
|
||||
docker:append_status("Images: " .. "pulling" .. " " .. image .. "...")
|
||||
local x_auth = nixio.bin.b64encode(json_stringify({serveraddress= server}))
|
||||
local res = dk.images:create(nil, {fromImage=image,_header={["X-Registry-Auth"]=x_auth}})
|
||||
local res = dk.images:create({query = {fromImage=image}, header={["X-Registry-Auth"]=x_auth}})
|
||||
if res and res.code == 200 then
|
||||
docker:append_status("done<br>")
|
||||
else
|
||||
@ -566,7 +566,7 @@ m.handle = function(self, state, data)
|
||||
end
|
||||
|
||||
docker:append_status("Container: " .. "create" .. " " .. name .. "...")
|
||||
local res = dk.containers:create(name, nil, create_body)
|
||||
local res = dk.containers:create({name = name, body = create_body})
|
||||
if res and res.code == 201 then
|
||||
docker:clear_status()
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/containers"))
|
@ -9,11 +9,11 @@ local docker = require "luci.model.docker"
|
||||
local dk = docker.new()
|
||||
|
||||
m = SimpleForm("docker", translate("Docker"))
|
||||
m.template = "docker/cbi/xsimpleform"
|
||||
m.template = "dockerman/cbi/xsimpleform"
|
||||
m.redirect = luci.dispatcher.build_url("admin", "services","docker", "networks")
|
||||
|
||||
docker_status = m:section(SimpleSection)
|
||||
docker_status.template="docker/apply_widget"
|
||||
docker_status.template = "dockerman/apply_widget"
|
||||
docker_status.err=nixio.fs.readfile(dk.options.status_path)
|
||||
if docker_status.err then docker:clear_status() end
|
||||
|
||||
@ -60,7 +60,7 @@ d.default = 0
|
||||
d:depends("dirver", "overlay")
|
||||
|
||||
d = s:option(DynamicList, "options", translate("Options"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.template = "dockerman/cbi/xdynlist"
|
||||
d.rmempty = true
|
||||
d.placeholder="com.docker.network.driver.mtu=1500"
|
||||
|
||||
@ -86,7 +86,7 @@ d.placeholder="10.1.1.0/24"
|
||||
d.datatype="ip4addr"
|
||||
|
||||
d = s:option(DynamicList, "aux_address", translate("Exclude IPs"))
|
||||
d.template = "docker/cbi/xdynlist"
|
||||
d.template = "dockerman/cbi/xdynlist"
|
||||
d.rmempty = true
|
||||
d.placeholder="my-route=10.1.1.1"
|
||||
|
||||
@ -191,7 +191,7 @@ m.handle = function(self, state, data)
|
||||
end
|
||||
|
||||
docker:append_status("Network: " .. "create" .. " " .. create_body.Name .. "...")
|
||||
local res = dk.networks:create(nil, nil, create_body)
|
||||
local res = dk.networks:create({body = create_body})
|
||||
if res and res.code == 201 then
|
||||
docker:clear_status()
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/services/docker/networks"))
|
@ -8,17 +8,17 @@ local docker = require "luci.model.docker"
|
||||
local uci = require "luci.model.uci"
|
||||
|
||||
function byte_format(byte)
|
||||
local suff = {"B", "KB", "MB", "GB", "TB"}
|
||||
for i=1, 5 do
|
||||
if byte > 1024 and i < 5 then
|
||||
byte = byte / 1024
|
||||
else
|
||||
return string.format("%.2f %s", byte, suff[i])
|
||||
end
|
||||
end
|
||||
local suff = {"B", "KB", "MB", "GB", "TB"}
|
||||
for i=1, 5 do
|
||||
if byte > 1024 and i < 5 then
|
||||
byte = byte / 1024
|
||||
else
|
||||
return string.format("%.2f %s", byte, suff[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local m = Map("docker", translate("Docker"))
|
||||
local m = Map("dockerman", translate("Docker"))
|
||||
local docker_info_table = {}
|
||||
-- docker_info_table['0OperatingSystem'] = {_key=translate("Operating System"),_value='-'}
|
||||
-- docker_info_table['1Architecture'] = {_key=translate("Architecture"),_value='-'}
|
||||
@ -41,13 +41,14 @@ s.containers_total = '-'
|
||||
s.images_total = '-'
|
||||
s.networks_total = '-'
|
||||
s.volumes_total = '-'
|
||||
local socket = luci.model.uci.cursor():get("docker", "local", "socket_path")
|
||||
local socket = luci.model.uci.cursor():get("dockerman", "local", "socket_path")
|
||||
if nixio.fs.access(socket) and (require "luci.model.docker").new():_ping().code == 200 then
|
||||
local dk = docker.new()
|
||||
-- local containers_list = dk.containers:list(nil, {all=true}).body
|
||||
-- local images_list = dk.images:list().body
|
||||
local volumes_list = dk.volumes:list().body.Volumes
|
||||
local networks_list = dk.networks:list().body
|
||||
local containers_list = dk.containers:list({query = {all=true}}).body
|
||||
local images_list = dk.images:list().body
|
||||
local vol = dk.volumes:list()
|
||||
local volumes_list = vol and vol.body and vol.body.Volumes or {}
|
||||
local networks_list = dk.networks:list().body or {}
|
||||
local docker_info = dk:info()
|
||||
-- docker_info_table['0OperatingSystem']._value = docker_info.body.OperatingSystem
|
||||
-- docker_info_table['1Architecture']._value = docker_info.body.Architecture
|
||||
@ -55,27 +56,27 @@ if nixio.fs.access(socket) and (require "luci.model.docker").new():_ping().code
|
||||
docker_info_table['3ServerVersion']._value = docker_info.body.ServerVersion
|
||||
docker_info_table['4ApiVersion']._value = docker_info.headers["Api-Version"]
|
||||
docker_info_table['5NCPU']._value = tostring(docker_info.body.NCPU)
|
||||
docker_info_table['6MemTotal']._value = tostring(byte_format(docker_info.body.MemTotal))
|
||||
docker_info_table['6MemTotal']._value = byte_format(docker_info.body.MemTotal)
|
||||
docker_info_table['7DockerRootDir']._value = docker_info.body.DockerRootDir
|
||||
docker_info_table['8IndexServerAddress']._value = docker_info.body.IndexServerAddress
|
||||
|
||||
-- s.images_used = 0
|
||||
-- for i, v in ipairs(images_list) do
|
||||
-- for ci,cv in ipairs(containers_list) do
|
||||
-- if v.Id == cv.ImageID then
|
||||
-- s.images_used = s.images_used + 1
|
||||
-- break
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
s.images_used = 0
|
||||
for i, v in ipairs(images_list) do
|
||||
for ci,cv in ipairs(containers_list) do
|
||||
if v.Id == cv.ImageID then
|
||||
s.images_used = s.images_used + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
s.containers_running = tostring(docker_info.body.ContainersRunning)
|
||||
-- s.images_used = tostring(s.images_used)
|
||||
s.images_used = tostring(s.images_used)
|
||||
s.containers_total = tostring(docker_info.body.Containers)
|
||||
s.images_total = tostring(docker_info.body.Images)
|
||||
s.images_total = tostring(#images_list)
|
||||
s.networks_total = tostring(#networks_list)
|
||||
s.volumes_total = tostring(#volumes_list)
|
||||
end
|
||||
s.template = "docker/overview"
|
||||
s.template = "dockerman/overview"
|
||||
|
||||
|
||||
s = m:section(NamedSection, "local", "section", translate("Setting"))
|
@ -11,7 +11,7 @@ local dk = docker.new()
|
||||
local containers, volumes
|
||||
local res = dk.volumes:list()
|
||||
if res.code <300 then volumes = res.body.Volumes else return end
|
||||
res = dk.containers:list(nil, {all=true})
|
||||
res = dk.containers:list({query = {all=true}})
|
||||
if res.code <300 then containers = res.body else return end
|
||||
|
||||
function get_volumes()
|
||||
@ -50,7 +50,7 @@ local volume_list = get_volumes()
|
||||
|
||||
-- m = Map("docker", translate("Docker"))
|
||||
m = SimpleForm("docker", translate("Docker"))
|
||||
m.template = "docker/cbi/xsimpleform"
|
||||
m.template = "dockerman/cbi/xsimpleform"
|
||||
m.submit=false
|
||||
m.reset=false
|
||||
|
||||
@ -72,7 +72,7 @@ volume_selecter.write = function(self, section, value)
|
||||
end
|
||||
|
||||
docker_status = m:section(SimpleSection)
|
||||
docker_status.template="docker/apply_widget"
|
||||
docker_status.template = "dockerman/apply_widget"
|
||||
docker_status.err=nixio.fs.readfile(dk.options.status_path)
|
||||
if docker_status.err then docker:clear_status() end
|
||||
|
||||
@ -82,7 +82,7 @@ action.rowcolors=false
|
||||
action.template="cbi/nullsection"
|
||||
btnremove = action:option(Button, "remove")
|
||||
btnremove.inputtitle= translate("Remove")
|
||||
btnremove.template="docker/cbi/inlinebutton"
|
||||
btnremove.template = "dockerman/cbi/inlinebutton"
|
||||
btnremove.inputstyle = "remove"
|
||||
btnremove.forcewrite = true
|
||||
btnremove.write = function(self, section)
|
||||
@ -101,7 +101,7 @@ btnremove.write = function(self, section)
|
||||
docker:clear_status()
|
||||
for _,vol in ipairs(volume_selected) do
|
||||
docker:append_status("Volumes: " .. "remove" .. " " .. vol .. "...")
|
||||
local msg = dk.volumes["remove"](dk, vol)
|
||||
local msg = dk.volumes["remove"](dk, {id = vol})
|
||||
if msg.code ~= 204 then
|
||||
docker:append_status("fail code:" .. msg.code.." ".. (msg.body.message and msg.body.message or msg.message).. "<br>")
|
||||
success = false
|
@ -13,16 +13,16 @@ local _docker = {}
|
||||
local update_image = function(self, image_name)
|
||||
local server = "index.docker.io"
|
||||
|
||||
local json_stringify = luci.json and luci.json.encode or luci.jsonc.stringify
|
||||
local json_stringify = luci.jsonc and luci.jsonc.stringify
|
||||
_docker:append_status("Images: " .. "pulling" .. " " .. image_name .. "...")
|
||||
local x_auth = nixio.bin.b64encode(json_stringify({serveraddress= server}))
|
||||
local res = self.images:create(nil, {fromImage=image_name, _header={["X-Registry-Auth"]=x_auth}})
|
||||
local res = self.images:create({query = {fromImage=image_name}, header={["X-Registry-Auth"]=x_auth}})
|
||||
if res and res.code < 300 then
|
||||
_docker:append_status("done<br>")
|
||||
else
|
||||
_docker:append_status("fail code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "<br>")
|
||||
end
|
||||
new_image_id = self.images:inspect(image_name).body.Id
|
||||
new_image_id = self.images:inspect({name = image_name}).body.Id
|
||||
return new_image_id, res
|
||||
end
|
||||
|
||||
@ -126,10 +126,10 @@ local get_config = function(old_config, old_host_config, old_network_setting, im
|
||||
return create_body, extra_network
|
||||
end
|
||||
|
||||
local upgrade = function(self, container_id)
|
||||
local upgrade = function(self, request)
|
||||
_docker:clear_status()
|
||||
-- get image name, image id, container name, configuration information
|
||||
local container_info = self.containers:inspect(container_id)
|
||||
local container_info = self.containers:inspect({id = request.id})
|
||||
if container_info.code > 300 and type(container_info.body) == "table" then
|
||||
return container_info
|
||||
end
|
||||
@ -148,7 +148,7 @@ local upgrade = function(self, container_id)
|
||||
end
|
||||
|
||||
_docker:append_status("Container: " .. "Stop" .. " " .. container_name .. "...")
|
||||
res = self.containers:stop(container_name)
|
||||
res = self.containers:stop({name = container_name})
|
||||
if res and res.code < 305 then
|
||||
_docker:append_status("done<br>")
|
||||
else
|
||||
@ -156,7 +156,7 @@ local upgrade = function(self, container_id)
|
||||
end
|
||||
|
||||
_docker:append_status("Container: rename" .. " " .. container_name .. " to ".. container_name .. "_old ...")
|
||||
res = self.containers:rename(container_name,{ name = container_name .. "_old" })
|
||||
res = self.containers:rename({name = container_name, query = { name = container_name .. "_old" }})
|
||||
if res and res.code < 300 then
|
||||
_docker:append_status("done<br>")
|
||||
else
|
||||
@ -164,12 +164,12 @@ local upgrade = function(self, container_id)
|
||||
end
|
||||
|
||||
-- handle config
|
||||
local image_config = self.images:inspect(old_image_id).body.Config
|
||||
local image_config = self.images:inspect({id = old_image_id}).body.Config
|
||||
local create_body, extra_network = get_config(old_config, old_host_config, old_network_setting, image_config)
|
||||
|
||||
-- create new container
|
||||
_docker:append_status("Container: Create" .. " " .. container_name .. "...")
|
||||
res = self.containers:create(container_name, nil, create_body)
|
||||
res = self.containers:create({name = container_name, body = create_body})
|
||||
if res and res.code > 300 then return res end
|
||||
_docker:append_status("done<br>")
|
||||
|
||||
@ -180,7 +180,7 @@ local upgrade = function(self, container_id)
|
||||
if v.Aliases and next(v.Aliases) == nil then v.Aliases =nil end
|
||||
|
||||
_docker:append_status("Networks: Connect" .. " " .. container_name .. "...")
|
||||
res = self.networks:connect(k, nil, {Container = container_name, EndpointConfig = v})
|
||||
res = self.networks:connect({id = k, body = {Container = container_name, EndpointConfig = v}})
|
||||
if res.code > 300 then return res end
|
||||
|
||||
_docker:append_status("done<br>")
|
||||
@ -189,32 +189,32 @@ local upgrade = function(self, container_id)
|
||||
return res
|
||||
end
|
||||
|
||||
local duplicate_config = function (self, container_id)
|
||||
local container_info = self.containers:inspect(container_id)
|
||||
local duplicate_config = function (self, request)
|
||||
local container_info = self.containers:inspect({id = request.id})
|
||||
if container_info.code > 300 and type(container_info.body) == "table" then return nil end
|
||||
local old_image_id = container_info.body.Image
|
||||
local old_config = container_info.body.Config
|
||||
local old_host_config = container_info.body.HostConfig
|
||||
local old_network_setting = container_info.body.NetworkSettings.Networks or {}
|
||||
local image_config = self.images:inspect(old_image_id).body.Config
|
||||
local image_config = self.images:inspect({id = old_image_id}).body.Config
|
||||
return get_config(old_config, old_host_config, old_network_setting, image_config)
|
||||
end
|
||||
|
||||
_docker.new = function(option)
|
||||
local option = option or {}
|
||||
options = {
|
||||
socket_path = option.socket_path or uci:get("docker", "local", "socket_path"),
|
||||
debug = option.debug or uci:get("docker", "local", "debug") == 'true' and true or false,
|
||||
debug_path = option.debug_path or uci:get("docker", "local", "debug_path")
|
||||
socket_path = option.socket_path or uci:get("dockerman", "local", "socket_path"),
|
||||
debug = option.debug or uci:get("dockerman", "local", "debug") == 'true' and true or false,
|
||||
debug_path = option.debug_path or uci:get("dockerman", "local", "debug_path")
|
||||
}
|
||||
local _new = docker.new(options)
|
||||
_new.options.status_path = uci:get("docker", "local", "status_path")
|
||||
_new.options.status_path = uci:get("dockerman", "local", "status_path")
|
||||
_new.containers_upgrade = upgrade
|
||||
_new.containers_duplicate_config = duplicate_config
|
||||
return _new
|
||||
end
|
||||
_docker.options={}
|
||||
_docker.options.status_path = uci:get("docker", "local", "status_path")
|
||||
_docker.options.status_path = uci:get("dockerman", "local", "status_path")
|
||||
|
||||
_docker.append_status=function(self,val)
|
||||
local file_docker_action_status=io.open(self.options.status_path, "a+")
|
||||
|
@ -8,7 +8,7 @@
|
||||
},
|
||||
path = {
|
||||
resource = resource,
|
||||
browser = url("admin/filebrowser")
|
||||
browser = url("admin/services/filebrowser")
|
||||
}
|
||||
}))
|
||||
%>>
|
@ -3,6 +3,7 @@
|
||||
<li id="cbi-tab-container_info"><a id="a-cbi-tab-container_info" href=""><%:Info%></a></li>
|
||||
<li id="cbi-tab-container_edit"><a id="a-cbi-tab-container_edit" href=""><%:Edit%></a></li>
|
||||
<li id="cbi-tab-container_stats"><a id="a-cbi-tab-container_stats" href=""><%:Stats%></a></li>
|
||||
<li id="cbi-tab-container_file"><a id="a-cbi-tab-container_file" href=""><%:File%></a></li>
|
||||
<li id="cbi-tab-container_logs"><a id="a-cbi-tab-container_logs" href=""><%:Logs%></a></li>
|
||||
</ul>
|
||||
|
||||
@ -12,7 +13,7 @@
|
||||
let path = p.split(re)
|
||||
let container_id = path[1].split('/')[0] || path[1]
|
||||
let action = path[1].split('/')[1] || "info"
|
||||
let actions=["info","edit","stats","logs"]
|
||||
let actions=["info","edit","stats","file","logs"]
|
||||
actions.forEach(function(item) {
|
||||
document.getElementById("a-cbi-tab-container_" + item).href= path[0]+"/admin/services/docker/container/"+container_id+'/'+item
|
||||
if (action === item) {
|
@ -0,0 +1,54 @@
|
||||
|
||||
<div id="upload-container" class="cbi-value cbi-value-last">
|
||||
<label class="cbi-value-title" for="archive"><%:Upload%></label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="file" name="upload_archive" accept="application/x-tar" id="upload_archive" />
|
||||
</div>
|
||||
<br>
|
||||
<label class="cbi-value-title" for="path"><%:Path%></label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="text" class="cbi-input-text" name="path" placeholder="/home/myfiles" id="path" />
|
||||
</div>
|
||||
<br>
|
||||
<div class="cbi-value-field">
|
||||
<input type="button"" class="cbi-button cbi-button-action important" id="upload" name="upload" value="<%:Upload%>" />
|
||||
<input type="button"" class="cbi-button cbi-button-action important" id="download" name="download" value="<%:Download%>" />
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
let btnUpload = document.getElementById('upload')
|
||||
btnUpload.onclick = function (e) {
|
||||
let uploadArchive = document.getElementById('upload_archive')
|
||||
let uploadPath = document.getElementById('path').value
|
||||
if (!uploadArchive.value || !uploadPath) {
|
||||
alert("<%:Please input the PATH and select the file !%>")
|
||||
return
|
||||
}
|
||||
let fileName = uploadArchive.files[0].name
|
||||
let formData = new FormData()
|
||||
formData.append('upload-filename', fileName)
|
||||
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.onload = function() {
|
||||
if (xhr.status == 200) {
|
||||
uploadArchive.value = ''
|
||||
alert("<%:Upload Success%> !")
|
||||
}
|
||||
else {
|
||||
alert("<%:Upload Error%>:" + xhr.statusText)
|
||||
}
|
||||
}
|
||||
xhr.send(formData)
|
||||
}
|
||||
let btnDownload = document.getElementById('download')
|
||||
btnDownload.onclick = function (e) {
|
||||
let downloadPath = document.getElementById('path').value
|
||||
if (!downloadPath) {
|
||||
alert("<%:Please input the PATH !%>")
|
||||
return
|
||||
}
|
||||
window.open("/cgi-bin/luci/admin/services/docker/container_get_archive/?id=<%=self.container%>&path=" + encodeURIComponent(downloadPath))
|
||||
}
|
||||
</script>
|
@ -162,8 +162,8 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
<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 -%>
|
||||
<span style="font-size: 2rem; color: #2dce89;"><%=self.images_total%></span>
|
||||
<!-- <span style="font-size: 1rem; color: #8898aa !important;">/<%=self.images_total%></span> -->
|
||||
<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 -%>
|
||||
</h4>
|
||||
</div>
|
@ -253,8 +253,8 @@ msgstr "保存docker status文件的位置"
|
||||
msgid "Enable Debug"
|
||||
msgstr "启用调试"
|
||||
|
||||
msgid "For debug, It shows all docker API actions of luci-app-dockermab in Debug Tempfile Path"
|
||||
msgstr "用于调试,它在调试临时文件路径中显示 luci-app-dockermab 的所有docker API操作"
|
||||
msgid "For debug, It shows all docker API actions of luci-app-dockerman in Debug Tempfile Path"
|
||||
msgstr "用于调试,在调试临时文件路径中显示 luci-app-dockerman 的所有 Docker API 操作"
|
||||
|
||||
msgid "Debug Tempfile Path"
|
||||
msgstr "调试临时文件路径"
|
||||
@ -328,5 +328,26 @@ msgstr "结束时间"
|
||||
msgid "Command line Error"
|
||||
msgstr "命令行错误"
|
||||
|
||||
msgid "Canceled"
|
||||
msgstr "已取消"
|
||||
msgid "Host Name"
|
||||
msgstr "主机名称"
|
||||
|
||||
msgid "The hostname to use for the container"
|
||||
msgstr "容器使用的主机名"
|
||||
|
||||
msgid "File"
|
||||
msgstr "文件"
|
||||
|
||||
msgid "Upload"
|
||||
msgstr "上传"
|
||||
|
||||
msgid "Download"
|
||||
msgstr "下载"
|
||||
|
||||
msgid "Path"
|
||||
msgstr "路径"
|
||||
|
||||
msgid "Upload Error"
|
||||
msgstr "上传错误"
|
||||
|
||||
msgid "Upload Success"
|
||||
msgstr "上传成功"
|
||||
|
@ -1,16 +1,18 @@
|
||||
#
|
||||
# Copyright (C) 2019 lisaac <lisaac.cn@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-lib-docker
|
||||
PKG_VERSION:=v0.1.1
|
||||
PKG_VERSION:=v0.3.0
|
||||
PKG_RELEASE:=beta
|
||||
PKG_MAINTAINER:=lisaac <https://github.com/lisaac/luci-lib-docker>
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_LICENSE:=AGPL-3.0
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/lisaac/luci-lib-docker.git
|
||||
PKG_SOURCE_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_SUBDIR)-$(PKG_VERSION).tar.gz
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
@ -28,6 +30,7 @@ define Package/$(PKG_NAME)/description
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
tar -xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(BUILD_DIR)
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
@ -40,7 +43,7 @@ endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci
|
||||
cp -pR ./luasrc/* $(1)/usr/lib/lua/luci
|
||||
cp -pR $(PKG_BUILD_DIR)/luasrc/* $(1)/usr/lib/lua/luci/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
|
@ -1,13 +1,13 @@
|
||||
require "nixio.util"
|
||||
require "luci.util"
|
||||
local json = require "luci.json"
|
||||
local jsonc = require "luci.jsonc"
|
||||
local nixio = require "nixio"
|
||||
local ltn12 = require "luci.ltn12"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
local urlencode = luci.util.urlencode or luci.http and luci.http.protocol and luci.http.protocol.urlencode
|
||||
local json_stringify = json.encode --luci.json and luci.json.encode or luci.jsonc.stringify
|
||||
local json_parse = json.decode --luci.json and luci.json.decode or luci.jsonc.parse
|
||||
local json_stringify = jsonc.stringify
|
||||
local json_parse = jsonc.parse
|
||||
|
||||
local chunksource = function(sock, buffer)
|
||||
buffer = buffer or ""
|
||||
@ -58,6 +58,16 @@ local chunksource = function(sock, buffer)
|
||||
end
|
||||
end
|
||||
|
||||
local chunksink = function (sock)
|
||||
return function(chunk, err)
|
||||
if not chunk then
|
||||
return sock:writeall("0\r\n\r\n")
|
||||
else
|
||||
return sock:writeall(("%X\r\n%s\r\n"):format(#chunk, tostring(chunk)))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local docker_stream_filter = function(buffer)
|
||||
buffer = buffer or ""
|
||||
if #buffer < 8 then
|
||||
@ -73,80 +83,44 @@ local docker_stream_filter = function(buffer)
|
||||
-- return string.sub(buffer, 9, valid_length + 8)
|
||||
end
|
||||
|
||||
local gen_http_req = function(options)
|
||||
local req
|
||||
options = options or {}
|
||||
options.protocol = options.protocol or "HTTP/1.1"
|
||||
req = (options.method or "GET") .. " " .. options.path .. " " .. options.protocol .. "\r\n"
|
||||
req = req .. "Host: " .. options.host .. "\r\n"
|
||||
req = req .. "User-Agent: " .. options.user_agent .. "\r\n"
|
||||
req = req .. "Connection: close\r\n"
|
||||
if type(options.header) == "table" then
|
||||
for k, v in pairs(options.header) do
|
||||
req = req .. k .. ": " .. v .."\r\n"
|
||||
end
|
||||
end
|
||||
if options.method == "POST" and type(options.conetnt) == "table" then
|
||||
local conetnt_json = json_stringify(options.conetnt)
|
||||
req = req .. "Content-Type: application/json\r\n"
|
||||
req = req .. "Content-Length: " .. #conetnt_json .. "\r\n"
|
||||
req = req .. "\r\n" .. conetnt_json
|
||||
elseif options.method == "PUT" and options.conetnt then
|
||||
req = req .. "Content-Type: application/x-tar\r\n"
|
||||
req = req .. "Content-Length: " .. #options.conetnt .. "\r\n"
|
||||
req = req .. "\r\n" .. options.conetnt
|
||||
else
|
||||
req = req .. "\r\n"
|
||||
end
|
||||
if options.debug then io.popen("echo '".. req .. "' >> " .. options.debug_path) end
|
||||
return req
|
||||
end
|
||||
|
||||
local send_http_socket = function(socket_path, req)
|
||||
local send_http_socket = function(socket_path, req_header, req_body, callback)
|
||||
local docker_socket = nixio.socket("unix", "stream")
|
||||
if docker_socket:connect(socket_path) ~= true then
|
||||
return {
|
||||
headers={
|
||||
code=497,
|
||||
message="bad socket path",
|
||||
protocol="HTTP/1.1"
|
||||
},
|
||||
body={
|
||||
message="can\'t connect to unix socket"
|
||||
}
|
||||
headers = {code=497, message="bad socket path", protocol="HTTP/1.1"},
|
||||
body = {message="can\'t connect to unix socket"}
|
||||
}
|
||||
end
|
||||
if docker_socket:send(req) == 0 then
|
||||
if docker_socket:send(req_header) == 0 then
|
||||
return {
|
||||
headers={
|
||||
code=498,
|
||||
message="bad socket path",
|
||||
protocol="HTTP/1.1"
|
||||
},
|
||||
body={
|
||||
message="can\'t send data to unix socket"
|
||||
}
|
||||
headers={code=498,message="bad socket path", protocol="HTTP/1.1"},
|
||||
body={message="can\'t send data to unix socket"}
|
||||
}
|
||||
end
|
||||
-- local data, err_code, err_msg, data_f = docker_socket:readall()
|
||||
-- docker_socket:close()
|
||||
|
||||
if req_body and type(req_body) == "function" and req_header and req_header:match("chunked") then
|
||||
-- chunked send
|
||||
req_body(chunksink(docker_socket))
|
||||
elseif req_body and type(req_body) == "function" then
|
||||
-- normal send by req_body function
|
||||
req_body(docker_socket)
|
||||
elseif req_body and type(req_body) == "table" then
|
||||
-- json
|
||||
docker_socket:send(json_stringify(req_body))
|
||||
elseif req_body then
|
||||
docker_socket:send(req_body)
|
||||
end
|
||||
|
||||
local linesrc = docker_socket:linesource()
|
||||
-- read socket using source http://w3.impa.br/~diego/software/luasocket/ltn12.html
|
||||
--http://lua-users.org/wiki/FiltersSourcesAndSinks
|
||||
|
||||
-- handle response header
|
||||
local line = linesrc()
|
||||
if not line then
|
||||
docker_socket:close()
|
||||
return {
|
||||
headers={
|
||||
code=499,
|
||||
message="bad socket path",
|
||||
protocol="HTTP/1.1"
|
||||
},
|
||||
body={
|
||||
message="no data receive from socket"
|
||||
}
|
||||
headers = {code=499, message="bad socket path", protocol="HTTP/1.1"},
|
||||
body = {message="no data receive from socket"}
|
||||
}
|
||||
end
|
||||
local response = {code = 0, headers = {}, body = {}}
|
||||
@ -172,64 +146,85 @@ local send_http_socket = function(socket_path, req)
|
||||
-- handle response body
|
||||
local body_buffer = linesrc(true)
|
||||
response.body = {}
|
||||
if response.headers["Transfer-Encoding"] == "chunked" then
|
||||
local source = chunksource(docker_socket, body_buffer)
|
||||
code = ltn12.pump.all(source, (ltn12.sink.table(response.body))) and response.code or 555
|
||||
response.code = code
|
||||
if type(callback) ~= "function" then
|
||||
if response.headers["Transfer-Encoding"] == "chunked" then
|
||||
local source = chunksource(docker_socket, body_buffer)
|
||||
code = ltn12.pump.all(source, (ltn12.sink.table(response.body))) and response.code or 555
|
||||
response.code = code
|
||||
else
|
||||
local body_source = ltn12.source.cat(ltn12.source.string(body_buffer), docker_socket:blocksource())
|
||||
code = ltn12.pump.all(body_source, (ltn12.sink.table(response.body))) and response.code or 555
|
||||
response.code = code
|
||||
end
|
||||
else
|
||||
local body_source = ltn12.source.cat(ltn12.source.string(body_buffer), docker_socket:blocksource())
|
||||
code = ltn12.pump.all(body_source, (ltn12.sink.table(response.body))) and response.code or 555
|
||||
response.code = code
|
||||
if response.headers["Transfer-Encoding"] == "chunked" then
|
||||
local source = chunksource(docker_socket, body_buffer)
|
||||
callback(response, source)
|
||||
else
|
||||
local body_source = ltn12.source.cat(ltn12.source.string(body_buffer), docker_socket:blocksource())
|
||||
callback(response, body_source)
|
||||
end
|
||||
end
|
||||
docker_socket:close()
|
||||
return response
|
||||
end
|
||||
|
||||
local send_http_require = function(options, method, api_group, api_action, name_or_id, request_qurey, request_body)
|
||||
local qurey
|
||||
local req_options = setmetatable({}, {__index = options})
|
||||
local gen_header = function(options, http_method, api_group, api_action, name_or_id, request)
|
||||
local header, query, path
|
||||
options = options or {}
|
||||
options.protocol = options.protocol or "HTTP/1.1"
|
||||
name_or_id = name_or_id ~= "" and name_or_id or nil
|
||||
|
||||
-- for docker action status
|
||||
-- if options.status_enabled then
|
||||
-- fs.writefile(options.status_path, api_group or "" .. " " .. api_action or "" .. " " .. name_or_id or "")
|
||||
-- end
|
||||
|
||||
-- request_qurey = request_qurey or {}
|
||||
-- request_body = request_body or {}
|
||||
if name_or_id == "" then
|
||||
name_or_id = nil
|
||||
end
|
||||
req_options.method = method
|
||||
req_options.path = (api_group and ("/" .. api_group) or "") .. (name_or_id and ("/" .. name_or_id) or "") .. (api_action and ("/" .. api_action) or "")
|
||||
req_options.header = {}
|
||||
if type(request_qurey) == "table" then
|
||||
for k, v in pairs(request_qurey) do
|
||||
if request and type(request.query) == "table" then
|
||||
local k, v
|
||||
for k, v in pairs(request.query) do
|
||||
if type(v) == "table" then
|
||||
if k ~= "_header" then
|
||||
qurey = (qurey and qurey .. "&" or "?") .. k .. "=" .. urlencode(json_stringify(v))
|
||||
else
|
||||
-- for http header
|
||||
for k1, v1 in pairs(v) do
|
||||
req_options.header[k1] = v1
|
||||
end
|
||||
end
|
||||
query = (query and query .. "&" or "?") .. k .. "=" .. urlencode(json_stringify(v))
|
||||
elseif type(v) == "boolean" then
|
||||
qurey = (qurey and qurey .. "&" or "?") .. k .. "=" .. (v and "true" or "false")
|
||||
query = (query and query .. "&" or "?") .. k .. "=" .. (v and "true" or "false")
|
||||
elseif type(v) == "number" or type(v) == "string" then
|
||||
qurey = (qurey and qurey .. "&" or "?") .. k .. "=" .. v
|
||||
query = (query and query .. "&" or "?") .. k .. "=" .. v
|
||||
end
|
||||
end
|
||||
end
|
||||
req_options.path = req_options.path .. (qurey or "")
|
||||
-- if type(request_body) == "table" then
|
||||
req_options.conetnt = request_body
|
||||
-- end
|
||||
local response = send_http_socket(req_options.socket_path, gen_http_req(req_options))
|
||||
-- for docker action status
|
||||
-- if options.status_enabled then
|
||||
-- fs.remove(options.status_path)
|
||||
-- end
|
||||
return response
|
||||
|
||||
path = (api_group and ("/" .. api_group) or "") .. (name_or_id and ("/" .. name_or_id) or "") .. (api_action and ("/" .. api_action) or "") .. (query or "")
|
||||
header = (http_method or "GET") .. " " .. path .. " " .. options.protocol .. "\r\n"
|
||||
header = header .. "Host: " .. options.host .. "\r\n"
|
||||
header = header .. "User-Agent: " .. options.user_agent .. "\r\n"
|
||||
header = header .. "Connection: close\r\n"
|
||||
|
||||
if request and type(request.header) == "table" then
|
||||
local k, v
|
||||
for k, v in pairs(request.header) do
|
||||
header = header .. k .. ": " .. v .. "\r\n"
|
||||
end
|
||||
end
|
||||
|
||||
-- when requst_body is function, we need to custom header using custom header
|
||||
if request and request.body and type(request.body) == "function" then
|
||||
if not header:match("Content-Length:") then
|
||||
header = header .. "Transfer-Encoding: chunked\r\n"
|
||||
end
|
||||
elseif http_method == "POST" and request and request.body and type(request.body) == "table" then
|
||||
local conetnt_json = json_stringify(request.body)
|
||||
header = header .. "Content-Type: application/json\r\n"
|
||||
header = header .. "Content-Length: " .. #conetnt_json .. "\r\n"
|
||||
elseif request and request.body and type(request.body) == "string" then
|
||||
header = header .. "Content-Length: " .. #request.body .. "\r\n"
|
||||
end
|
||||
header = header .. "\r\n"
|
||||
if options.debug then io.popen("echo '".. header .. "' >> " .. options.debug_path) end
|
||||
return header
|
||||
end
|
||||
|
||||
local call_docker = function(options, http_method, api_group, api_action, name_or_id, request, callback)
|
||||
local req_options = setmetatable({}, {__index = options})
|
||||
|
||||
local req_header = gen_header(req_options, http_method, api_group, api_action, name_or_id, request)
|
||||
local req_body = request and request.body or nil
|
||||
|
||||
return send_http_socket(req_options.socket_path, req_header, req_body, callback)
|
||||
end
|
||||
|
||||
local gen_api = function(_table, http_method, api_group, api_action)
|
||||
@ -244,28 +239,29 @@ local gen_api = function(_table, http_method, api_group, api_action)
|
||||
_api_action = "json"
|
||||
end
|
||||
|
||||
local fp = function(self, name_or_id, request_qurey, request_body)
|
||||
local fp = function(self, request, callback)
|
||||
local name_or_id = request and (request.name or request.id or request.name_or_id) or nil
|
||||
if api_action == "list" then
|
||||
if (name_or_id ~= "" and name_or_id ~= nil) then
|
||||
if api_group == "images" then
|
||||
name_or_id = nil
|
||||
else
|
||||
request_qurey = request_qurey or {}
|
||||
request_qurey.filters = request_qurey.filters or {}
|
||||
request_qurey.filters.name = request_qurey.filters.name or {}
|
||||
request_qurey.filters.name[#request_qurey.filters.name + 1] = name_or_id
|
||||
request.query = request and request.query or {}
|
||||
request.query.filters = request.query.filters or {}
|
||||
request.query.filters.name = request.query.filters.name or {}
|
||||
request.query.filters.name[#request.query.filters.name + 1] = name_or_id
|
||||
name_or_id = nil
|
||||
end
|
||||
end
|
||||
elseif api_action == "create" then
|
||||
if (name_or_id ~= "" and name_or_id ~= nil) then
|
||||
request_qurey = request_qurey or {}
|
||||
request_qurey.name = request_qurey.name or name_or_id
|
||||
request.query = request and request.query or {}
|
||||
request.query.name = request.query.name or name_or_id
|
||||
name_or_id = nil
|
||||
end
|
||||
elseif api_action == "logs" then
|
||||
local body_buffer = ""
|
||||
local response = send_http_require(self.options, http_method, api_group, _api_action, name_or_id, request_qurey, request_body)
|
||||
local response = call_docker(self.options, http_method, api_group, _api_action, name_or_id, request, callback)
|
||||
if response.code >= 200 and response.code < 300 then
|
||||
for i, v in ipairs(response.body) do
|
||||
body_buffer = body_buffer .. docker_stream_filter(response.body[i])
|
||||
@ -274,7 +270,7 @@ local gen_api = function(_table, http_method, api_group, api_action)
|
||||
end
|
||||
return response
|
||||
end
|
||||
local response = send_http_require(self.options, http_method, api_group, _api_action, name_or_id, request_qurey, request_body)
|
||||
local response = call_docker(self.options, http_method, api_group, _api_action, name_or_id, request, callback)
|
||||
if response.headers and response.headers["Content-Type"] == "application/json" then
|
||||
if #response.body == 1 then
|
||||
response.body = json_parse(response.body[1])
|
||||
|
Loading…
Reference in New Issue
Block a user