luci-lib-docker: update conding style

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
This commit is contained in:
Florian Eckert 2020-07-28 14:15:46 +02:00
parent edb53058d0
commit a722abd279

View file

@ -2,6 +2,7 @@
LuCI - Lua Configuration Interface LuCI - Lua Configuration Interface
Copyright 2019 lisaac <https://github.com/lisaac/luci-lib-docker> Copyright 2019 lisaac <https://github.com/lisaac/luci-lib-docker>
]]-- ]]--
require "nixio.util" require "nixio.util"
require "luci.util" require "luci.util"
local jsonc = require "luci.jsonc" local jsonc = require "luci.jsonc"
@ -15,44 +16,55 @@ local json_parse = jsonc.parse
local chunksource = function(sock, buffer) local chunksource = function(sock, buffer)
buffer = buffer or "" buffer = buffer or ""
return function() return function()
local output local output
local _, endp, count = buffer:find("^([0-9a-fA-F]+)\r\n") local _, endp, count = buffer:find("^([0-9a-fA-F]+)\r\n")
if not count then if not count then
local newblock, code = sock:recv(1024) local newblock, code = sock:recv(1024)
if not newblock then return nil, code end if not newblock then
return nil, code
end
buffer = buffer .. newblock buffer = buffer .. newblock
_, endp, count = buffer:find("^([0-9a-fA-F]+)\r\n") _, endp, count = buffer:find("^([0-9a-fA-F]+)\r\n")
end end
count = tonumber(count, 16) count = tonumber(count, 16)
if not count then if not count then
return nil, -1, "invalid encoding" return nil, -1, "invalid encoding"
elseif count == 0 then -- finial elseif count == 0 then -- finial
return nil return nil
elseif count <= #buffer - endp then elseif count <= #buffer - endp then -- data >= count
--data >= count
output = buffer:sub(endp + 1, endp + count) output = buffer:sub(endp + 1, endp + count)
if count == #buffer - endp then -- [data] if count == #buffer - endp then -- [data]
buffer = buffer:sub(endp + count + 1) buffer = buffer:sub(endp + count + 1)
count, code = sock:recvall(2) --read \r\n count, code = sock:recvall(2) --read \r\n
if not count then return nil, code end if not count then
return nil, code
end
elseif count + 1 == #buffer - endp then -- [data]\r elseif count + 1 == #buffer - endp then -- [data]\r
buffer = buffer:sub(endp + count + 2) buffer = buffer:sub(endp + count + 2)
count, code = sock:recvall(1) --read \n count, code = sock:recvall(1) --read \n
if not count then return nil, code end if not count then
return nil, code
end
else -- [data]\r\n[count]\r\n[data]... else -- [data]\r\n[count]\r\n[data]...
buffer = buffer:sub(endp + count + 3) -- cut buffer buffer = buffer:sub(endp + count + 3) -- cut buffer
end end
return output return output
else else -- data < count
-- data < count
output = buffer:sub(endp + 1, endp + count) output = buffer:sub(endp + 1, endp + count)
buffer = buffer:sub(endp + count + 1) buffer = buffer:sub(endp + count + 1)
local remain, code = sock:recvall(count - #output) --need read remaining local remain, code = sock:recvall(count - #output) --need read remaining
if not remain then return nil, code end if not remain then
return nil, code
end
output = output .. remain output = output .. remain
count, code = sock:recvall(2) --read \r\n count, code = sock:recvall(2) --read \r\n
if not count then return nil, code end if not count then
return nil, code
end
return output return output
end end
end end
@ -74,21 +86,23 @@ local docker_stream_filter = function(buffer)
return "" return ""
end end
local stream_type = ((string.byte(buffer, 1) == 1) and "stdout") or ((string.byte(buffer, 1) == 2) and "stderr") or ((string.byte(buffer, 1) == 0) and "stdin") or "stream_err" local stream_type = ((string.byte(buffer, 1) == 1) and "stdout") or ((string.byte(buffer, 1) == 2) and "stderr") or ((string.byte(buffer, 1) == 0) and "stdin") or "stream_err"
local valid_length = local valid_length = tonumber(string.byte(buffer, 5)) * 256 * 256 * 256 + tonumber(string.byte(buffer, 6)) * 256 * 256 + tonumber(string.byte(buffer, 7)) * 256 + tonumber(string.byte(buffer, 8))
tonumber(string.byte(buffer, 5)) * 256 * 256 * 256 + tonumber(string.byte(buffer, 6)) * 256 * 256 + tonumber(string.byte(buffer, 7)) * 256 + tonumber(string.byte(buffer, 8))
if valid_length > #buffer + 8 then if valid_length > #buffer + 8 then
return "" return ""
end end
return stream_type .. ": " .. string.sub(buffer, 9, valid_length + 8) return stream_type .. ": " .. string.sub(buffer, 9, valid_length + 8)
-- return string.sub(buffer, 9, valid_length + 8)
end end
local open_socket = function(req_options) local open_socket = function(req_options)
local socket local socket
if type(req_options) ~= "table" then return socket end if type(req_options) ~= "table" then
return socket
end
if req_options.socket_path then if req_options.socket_path then
socket = nixio.socket("unix", "stream") socket = nixio.socket("unix", "stream")
if socket:connect(req_options.socket_path) ~= true then return nil end if socket:connect(req_options.socket_path) ~= true then
return nil
end
elseif req_options.host and req_options.port then elseif req_options.host and req_options.port then
socket = nixio.connect(req_options.host, req_options.port) socket = nixio.connect(req_options.host, req_options.port)
end end
@ -102,8 +116,14 @@ end
local send_http_socket = function(docker_socket, req_header, req_body, callback) local send_http_socket = function(docker_socket, req_header, req_body, callback)
if docker_socket:send(req_header) == 0 then if docker_socket:send(req_header) == 0 then
return { return {
headers={code=498,message="bad path", protocol="HTTP/1.1"}, headers={
body={message="can\'t send data to socket"} code=498,
message="bad path",
protocol="HTTP/1.1"
},
body={
message="can\'t send data to socket"
}
} }
end end
@ -116,36 +136,55 @@ local send_http_socket = function(docker_socket, req_header, req_body, callback)
elseif req_body and type(req_body) == "table" then elseif req_body and type(req_body) == "table" then
-- json -- json
docker_socket:send(json_stringify(req_body)) docker_socket:send(json_stringify(req_body))
if options.debug then io.popen("echo '".. json_stringify(req_body) .. "' >> " .. options.debug_path) end if options.debug then
io.popen("echo '".. json_stringify(req_body) .. "' >> " .. options.debug_path)
end
elseif req_body then elseif req_body then
docker_socket:send(req_body) docker_socket:send(req_body)
if options.debug then io.popen("echo '".. req_body .. "' >> " .. options.debug_path) end if options.debug then
io.popen("echo '".. req_body .. "' >> " .. options.debug_path)
end
end end
local linesrc = docker_socket:linesource() local linesrc = docker_socket:linesource()
-- read socket using source http://w3.impa.br/~diego/software/luasocket/ltn12.html -- read socket using source http://w3.impa.br/~diego/software/luasocket/ltn12.html
--http://lua-users.org/wiki/FiltersSourcesAndSinks -- http://lua-users.org/wiki/FiltersSourcesAndSinks
-- handle response header -- handle response header
local line = linesrc() local line = linesrc()
if not line then if not line then
docker_socket:close() docker_socket:close()
return { return {
headers = {code=499, message="bad socket path", protocol="HTTP/1.1"}, headers = {
body = {message="no data receive from socket"} code=499,
message="bad socket path",
protocol="HTTP/1.1"
},
body = {
message="no data receive from socket"
}
} }
end end
local response = {code = 0, headers = {}, body = {}}
local response = {
code = 0,
headers = {},
body = {}
}
local p, code, msg = line:match("^([%w./]+) ([0-9]+) (.*)") local p, code, msg = line:match("^([%w./]+) ([0-9]+) (.*)")
response.protocol = p response.protocol = p
response.code = tonumber(code) response.code = tonumber(code)
response.message = msg response.message = msg
line = linesrc() line = linesrc()
while line and line ~= "" do while line and line ~= "" do
local key, val = line:match("^([%w-]+)%s?:%s?(.*)") local key, val = line:match("^([%w-]+)%s?:%s?(.*)")
if key and key ~= "Status" then if key and key ~= "Status" then
if type(response.headers[key]) == "string" then if type(response.headers[key]) == "string" then
response.headers[key] = {response.headers[key], val} response.headers[key] = {
response.headers[key],
val
}
elseif type(response.headers[key]) == "table" then elseif type(response.headers[key]) == "table" then
response.headers[key][#response.headers[key] + 1] = val response.headers[key][#response.headers[key] + 1] = val
else else
@ -154,9 +193,11 @@ local send_http_socket = function(docker_socket, req_header, req_body, callback)
end end
line = linesrc() line = linesrc()
end end
-- handle response body -- handle response body
local body_buffer = linesrc(true) local body_buffer = linesrc(true)
response.body = {} response.body = {}
if type(callback) ~= "function" then if type(callback) ~= "function" then
if response.headers["Transfer-Encoding"] == "chunked" then if response.headers["Transfer-Encoding"] == "chunked" then
local source = chunksource(docker_socket, body_buffer) local source = chunksource(docker_socket, body_buffer)
@ -196,6 +237,7 @@ local gen_header = function(options, http_method, api_group, api_action, name_or
end end
end end
end end
path = (api_group and ("/" .. api_group) or "") .. (name_or_id and ("/" .. name_or_id) or "") .. (api_action and ("/" .. api_action) or "") .. (query or "") 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 = (http_method or "GET") .. " " .. path .. " " .. options.protocol .. "\r\n"
header = header .. "Host: " .. options.host .. "\r\n" header = header .. "Host: " .. options.host .. "\r\n"
@ -221,15 +263,27 @@ local gen_header = function(options, http_method, api_group, api_action, name_or
elseif request and request.body and type(request.body) == "string" then elseif request and request.body and type(request.body) == "string" then
header = header .. "Content-Length: " .. #request.body .. "\r\n" header = header .. "Content-Length: " .. #request.body .. "\r\n"
end end
header = header .. "\r\n" header = header .. "\r\n"
if options.debug then io.popen("echo '".. header .. "' >> " .. options.debug_path) end if options.debug then
io.popen("echo '".. header .. "' >> " .. options.debug_path)
end
return header return header
end end
local call_docker = function(options, http_method, api_group, api_action, name_or_id, request, callback) local call_docker = function(options, http_method, api_group, api_action, name_or_id, request, callback)
local req_options = setmetatable({}, {__index = options}) 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_header = gen_header(req_options, http_method, api_group, api_action, name_or_id, request)
local req_body = request and request.body or nil local req_body = request and request.body or nil
local docker_socket = open_socket(req_options) local docker_socket = open_socket(req_options)
@ -237,16 +291,23 @@ local call_docker = function(options, http_method, api_group, api_action, name_o
return send_http_socket(docker_socket, req_header, req_body, callback) return send_http_socket(docker_socket, req_header, req_body, callback)
else else
return { return {
headers = {code=497, message="bad socket path or host", protocol="HTTP/1.1"}, headers = {
body = {message="can\'t connect to socket"} code=497,
message="bad socket path or host",
protocol="HTTP/1.1"
},
body = {
message="can\'t connect to socket"
}
} }
end end
end end
local gen_api = function(_table, http_method, api_group, api_action) local gen_api = function(_table, http_method, api_group, api_action)
local _api_action local _api_action
if api_action == "get_archive" or api_action == "put_archive" then if api_action == "get_archive" or api_action == "put_archive" then
_api_action = "archive" api_action = "archive"
elseif api_action == "df" then elseif api_action == "df" then
_api_action = "system/df" _api_action = "system/df"
elseif api_action ~= "list" and api_action ~= "inspect" and api_action ~= "remove" then elseif api_action ~= "list" and api_action ~= "inspect" and api_action ~= "remove" then
@ -257,6 +318,7 @@ local gen_api = function(_table, http_method, api_group, api_action)
local fp = function(self, request, callback) local fp = function(self, request, callback)
local name_or_id = request and (request.name or request.id or request.name_or_id) or nil local name_or_id = request and (request.name or request.id or request.name_or_id) or nil
if api_action == "list" then if api_action == "list" then
if (name_or_id ~= "" and name_or_id ~= nil) then if (name_or_id ~= "" and name_or_id ~= nil) then
if api_group == "images" then if api_group == "images" then
@ -277,7 +339,13 @@ local gen_api = function(_table, http_method, api_group, api_action)
end end
elseif api_action == "logs" then elseif api_action == "logs" then
local body_buffer = "" local body_buffer = ""
local response = call_docker(self.options, http_method, api_group, _api_action, name_or_id, request, callback) 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 if response.code >= 200 and response.code < 300 then
for i, v in ipairs(response.body) do for i, v in ipairs(response.body) do
body_buffer = body_buffer .. docker_stream_filter(response.body[i]) body_buffer = body_buffer .. docker_stream_filter(response.body[i])
@ -286,7 +354,9 @@ local gen_api = function(_table, http_method, api_group, api_action)
end end
return response return response
end end
local response = call_docker(self.options, http_method, api_group, _api_action, name_or_id, request, callback) 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.headers and response.headers["Content-Type"] == "application/json" then
if #response.body == 1 then if #response.body == 1 then
response.body = json_parse(response.body[1]) response.body = json_parse(response.body[1])
@ -308,7 +378,13 @@ local gen_api = function(_table, http_method, api_group, api_action)
end end
end end
local _docker = {containers = {}, exec = {}, images = {}, networks = {}, volumes = {}} local _docker = {
containers = {},
exec = {},
images = {},
networks = {},
volumes = {}
}
gen_api(_docker, "GET", "containers", "list") gen_api(_docker, "GET", "containers", "list")
gen_api(_docker, "POST", "containers", "create") gen_api(_docker, "POST", "containers", "create")
@ -370,6 +446,7 @@ gen_api(_docker, "GET", nil, "df")
function _docker.new(options) function _docker.new(options)
local docker = {} local docker = {}
local _options = options or {} local _options = options or {}
docker.options = { docker.options = {
socket_path = _options.socket_path or nil, socket_path = _options.socket_path or nil,
host = _options.socket_path and "localhost" or _options.host, host = _options.socket_path and "localhost" or _options.host,
@ -384,6 +461,7 @@ function _docker.new(options)
debug = _options.debug or false, debug = _options.debug or false,
debug_path = _options.debug and _options.debug_path or nil debug_path = _options.debug and _options.debug_path or nil
} }
setmetatable( setmetatable(
docker, docker,
{ {
@ -396,6 +474,7 @@ function _docker.new(options)
end end
} }
) )
setmetatable( setmetatable(
docker.containers, docker.containers,
{ {
@ -406,6 +485,7 @@ function _docker.new(options)
end end
} }
) )
setmetatable( setmetatable(
docker.networks, docker.networks,
{ {
@ -416,6 +496,7 @@ function _docker.new(options)
end end
} }
) )
setmetatable( setmetatable(
docker.images, docker.images,
{ {
@ -426,6 +507,7 @@ function _docker.new(options)
end end
} }
) )
setmetatable( setmetatable(
docker.volumes, docker.volumes,
{ {
@ -436,6 +518,7 @@ function _docker.new(options)
end end
} }
) )
setmetatable( setmetatable(
docker.exec, docker.exec,
{ {
@ -446,6 +529,7 @@ function _docker.new(options)
end end
} }
) )
return docker return docker
end end