luci-app-dockerman: sync with upstream source
This commit is contained in:
parent
2505cf346c
commit
40345ce2a4
@ -4,6 +4,7 @@ Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
require "math"
|
||||
local uci = luci.model.uci.cursor()
|
||||
local docker = require "luci.model.docker"
|
||||
local dk = docker.new()
|
||||
@ -14,10 +15,23 @@ local images = dk.images:list().body
|
||||
local networks = dk.networks:list().body
|
||||
local containers = dk.containers:list(nil, {all=true}).body
|
||||
|
||||
local is_quot_complete = function(str)
|
||||
if not str then return true end
|
||||
local num = 0, w
|
||||
for w in str:gmatch("[\"\']") do
|
||||
num = num + 1
|
||||
end
|
||||
if math.fmod(num, 2) ~= 0 then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- reslvo default config
|
||||
local default_config = { }
|
||||
if cmd_line and cmd_line:match("^docker.+") then
|
||||
local key = nil
|
||||
local key = nil, _key
|
||||
--cursor = 0: docker run
|
||||
--cursor = 1: resloving para
|
||||
--cursor = 2: resloving image
|
||||
@ -26,6 +40,24 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
for w in cmd_line:gmatch("[^%s]+") do
|
||||
-- skip '\'
|
||||
if w == '\\' then
|
||||
elseif _key then
|
||||
-- there is a value that unpair quotation marks:
|
||||
-- "i was a ok man"
|
||||
-- now we only get: "i
|
||||
if _key == "mount" or _key == "link" or _key == "env" or _key == "dns" or _key == "port" or _key == "device" or _key == "tmpfs" then
|
||||
default_config[_key][#default_config[_key]] = default_config[_key][#default_config[_key]] .. " " .. w
|
||||
if is_quot_complete(default_config[_key][#default_config[_key]]) then
|
||||
-- clear quotation marks
|
||||
default_config[_key][#default_config[_key]] = default_config[_key][#default_config[_key]]:gsub("[\"\']", "")
|
||||
_key = nil
|
||||
end
|
||||
else
|
||||
default_config[_key] = default_config[_key] .. " ".. w
|
||||
if is_quot_complete(default_config[_key]) then
|
||||
default_config[_key] = default_config[_key]:gsub("[\"\']", "")
|
||||
_key = nil
|
||||
end
|
||||
end
|
||||
-- start with '-'
|
||||
elseif w:match("^%-+.+") and cursor <= 1 then
|
||||
--key=value
|
||||
@ -33,7 +65,7 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
key, val = w:match("^%-%-(.-)=(.+)")
|
||||
-- -dit
|
||||
if not key then key = w:match("^%-%-(.+)") end
|
||||
|
||||
|
||||
if not key then
|
||||
key = w:match("^%-(.+)")
|
||||
if key:match("i") or key:match("t") or key:match("d") then
|
||||
@ -43,7 +75,7 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
key = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if key == "v" or key == "volume" then
|
||||
key = "mount"
|
||||
elseif key == "p" then
|
||||
@ -72,6 +104,12 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
else
|
||||
default_config[key] = val
|
||||
end
|
||||
-- if there are " or ' in val and separate by space, we need keep the _key to link with next w
|
||||
if is_quot_complete(val) then
|
||||
_key = nil
|
||||
else
|
||||
_key = key
|
||||
end
|
||||
-- clear key
|
||||
key = nil
|
||||
end
|
||||
@ -87,6 +125,12 @@ if cmd_line and cmd_line:match("^docker.+") then
|
||||
if key == "cpus" or key == "cpushare" or key == "memory" or key == "blkioweight" or key == "device" or key == "tmpfs" then
|
||||
default_config["advance"] = 1
|
||||
end
|
||||
-- if there are " or ' in val and separate by space, we need keep the _key to link with next w
|
||||
if is_quot_complete(w) then
|
||||
_key = nil
|
||||
else
|
||||
_key = key
|
||||
end
|
||||
key = nil
|
||||
cursor = 1
|
||||
--image and command
|
||||
|
||||
@ -1,57 +1,57 @@
|
||||
<style type="text/css">
|
||||
#docker_apply_overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
display: none;
|
||||
z-index: 20000;
|
||||
}
|
||||
#docker_apply_overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
display: none;
|
||||
z-index: 20000;
|
||||
}
|
||||
|
||||
#docker_apply_overlay .alert-message {
|
||||
position: relative;
|
||||
top: 10%;
|
||||
width: 60%;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
min-height: 32px;
|
||||
align-items: center;
|
||||
}
|
||||
#docker_apply_overlay .alert-message {
|
||||
position: relative;
|
||||
top: 10%;
|
||||
width: 60%;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
min-height: 32px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#docker_apply_overlay .alert-message > h4,
|
||||
#docker_apply_overlay .alert-message > p,
|
||||
#docker_apply_overlay .alert-message > div {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
#docker_apply_overlay .alert-message > h4,
|
||||
#docker_apply_overlay .alert-message > p,
|
||||
#docker_apply_overlay .alert-message > div {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
#docker_apply_overlay .alert-message > img {
|
||||
margin-right: 1em;
|
||||
flex-basis: 32px;
|
||||
}
|
||||
#docker_apply_overlay .alert-message > img {
|
||||
margin-right: 1em;
|
||||
flex-basis: 32px;
|
||||
}
|
||||
|
||||
body.apply-overlay-active {
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
}
|
||||
body.apply-overlay-active {
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
body.apply-overlay-active #docker_apply_overlay {
|
||||
display: block;
|
||||
}
|
||||
body.apply-overlay-active #docker_apply_overlay {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var xhr = new XHR(),
|
||||
uci_apply_rollback = <%=math.max(luci.config and luci.config.apply and luci.config.apply.rollback or 30, 30)%>,
|
||||
uci_apply_holdoff = <%=math.max(luci.config and luci.config.apply and luci.config.apply.holdoff or 4, 1)%>,
|
||||
uci_apply_timeout = <%=math.max(luci.config and luci.config.apply and luci.config.apply.timeout or 5, 1)%>,
|
||||
uci_apply_display = <%=math.max(luci.config and luci.config.apply and luci.config.apply.display or 1.5, 1)%>,
|
||||
was_xhr_poll_running = false;
|
||||
var xhr = new XHR(),
|
||||
uci_apply_rollback = <%=math.max(luci.config and luci.config.apply and luci.config.apply.rollback or 30, 30)%>,
|
||||
uci_apply_holdoff = <%=math.max(luci.config and luci.config.apply and luci.config.apply.holdoff or 4, 1)%>,
|
||||
uci_apply_timeout = <%=math.max(luci.config and luci.config.apply and luci.config.apply.timeout or 5, 1)%>,
|
||||
uci_apply_display = <%=math.max(luci.config and luci.config.apply and luci.config.apply.display or 1.5, 1)%>,
|
||||
was_xhr_poll_running = false;
|
||||
|
||||
function docker_status_message(type, content) {
|
||||
document.getElementById('docker_apply_overlay') || document.body.insertAdjacentHTML("beforeend",'<div id="docker_apply_overlay"><div class="alert-message"></div></div>')
|
||||
var overlay = document.getElementById('docker_apply_overlay')
|
||||
var overlay = document.getElementById('docker_apply_overlay')
|
||||
message = overlay.querySelector('.alert-message');
|
||||
|
||||
if (message && type) {
|
||||
@ -65,7 +65,7 @@ function docker_status_message(type, content) {
|
||||
message.innerHTML = content;
|
||||
|
||||
document.body.classList.add('apply-overlay-active');
|
||||
|
||||
document.body.scrollTop = document.documentElement.scrollTop = 0;
|
||||
if (!was_xhr_poll_running) {
|
||||
was_xhr_poll_running = XHR.running();
|
||||
XHR.halt();
|
||||
@ -80,58 +80,53 @@ function docker_status_message(type, content) {
|
||||
}
|
||||
var loading_msg="Loadding.."
|
||||
function uci_confirm_docker() {
|
||||
var tt;
|
||||
|
||||
docker_status_message('notice');
|
||||
|
||||
var call = function(r, resjson, duration) {
|
||||
|
||||
var tt;
|
||||
docker_status_message('notice');
|
||||
var call = function(r, resjson, duration) {
|
||||
if (r && r.status === 200 ) {
|
||||
var indicator = document.querySelector('.uci_change_indicator');
|
||||
if (indicator) indicator.style.display = 'none';
|
||||
docker_status_message('notice', '<%:Docker actions done.%>');
|
||||
window.clearTimeout(tt);
|
||||
return;
|
||||
}
|
||||
loading_msg = resjson?resjson.info:loading_msg
|
||||
// var delay = isNaN(duration) ? 0 : Math.max(1000 - duration, 0);
|
||||
var delay =1000
|
||||
window.setTimeout(function() {
|
||||
xhr.get('<%=url("admin/docker/confirm")%>', null, call, uci_apply_timeout * 1000);
|
||||
}, delay);
|
||||
};
|
||||
var indicator = document.querySelector('.uci_change_indicator');
|
||||
if (indicator) indicator.style.display = 'none';
|
||||
docker_status_message('notice', '<%:Docker actions done.%>');
|
||||
window.clearTimeout(tt);
|
||||
return;
|
||||
}
|
||||
loading_msg = resjson?resjson.info:loading_msg
|
||||
// var delay = isNaN(duration) ? 0 : Math.max(1000 - duration, 0);
|
||||
var delay =1000
|
||||
window.setTimeout(function() {
|
||||
xhr.get('<%=url("admin/docker/confirm")%>', null, call, uci_apply_timeout * 1000);
|
||||
}, delay);
|
||||
};
|
||||
|
||||
var tick = function() {
|
||||
var now = Date.now();
|
||||
var tick = function() {
|
||||
var now = Date.now();
|
||||
|
||||
docker_status_message('notice',
|
||||
'<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
|
||||
loading_msg);
|
||||
docker_status_message('notice',
|
||||
'<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
|
||||
loading_msg);
|
||||
|
||||
tt = window.setTimeout(tick, 200);
|
||||
ts = now;
|
||||
};
|
||||
|
||||
tick();
|
||||
|
||||
/* wait a few seconds for the settings to become effective */
|
||||
window.setTimeout(call, Math.max(uci_apply_holdoff * 1000 , 1));
|
||||
}
|
||||
// document.getElementsByTagName("form")[0].addEventListener("submit", (e)=>{
|
||||
// uci_confirm_docker()
|
||||
// })
|
||||
tt = window.setTimeout(tick, 200);
|
||||
ts = now;
|
||||
};
|
||||
tick();
|
||||
/* wait a few seconds for the settings to become effective */
|
||||
window.setTimeout(call, Math.max(uci_apply_holdoff * 1000 , 1));
|
||||
}
|
||||
// document.getElementsByTagName("form")[0].addEventListener("submit", (e)=>{
|
||||
// uci_confirm_docker()
|
||||
// })
|
||||
|
||||
function fnSubmitForm(el){
|
||||
if (el.id != "cbid.table.1._new") {
|
||||
uci_confirm_docker()
|
||||
}
|
||||
uci_confirm_docker()
|
||||
}
|
||||
}
|
||||
|
||||
<% if self.err then -%>
|
||||
docker_status_message('warning', `<%=self.err%>`);
|
||||
document.getElementById('docker_apply_overlay').addEventListener("click", (e)=>{
|
||||
docker_status_message()
|
||||
})
|
||||
docker_status_message('warning', `<%=self.err%>`);
|
||||
document.getElementById('docker_apply_overlay').addEventListener("click", (e)=>{
|
||||
docker_status_message()
|
||||
})
|
||||
<%- end %>
|
||||
|
||||
window.onload= function (){
|
||||
|
||||
@ -1,20 +1,91 @@
|
||||
<%+cbi/valueheader%>
|
||||
<style type="text/css">
|
||||
#dialog_reslov {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
display: none;
|
||||
z-index: 20000;
|
||||
}
|
||||
|
||||
#dialog_reslov .dialog_box {
|
||||
position: relative;
|
||||
background: rgba(255, 255, 255);
|
||||
top: 10%;
|
||||
width: 50%;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
min-height: 50%;
|
||||
max-height: auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#dialog_reslov .dialog_line {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
#dialog_reslov .dialog_box>h4,
|
||||
#dialog_reslov .dialog_box>p,
|
||||
#dialog_reslov .dialog_box>div {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
#dialog_reslov .dialog_box>img {
|
||||
margin-right: 1em;
|
||||
flex-basis: 32px;
|
||||
}
|
||||
|
||||
body.dialog-reslov-active {
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
body.dialog-reslov-active #dialog_reslov {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function resolv_container(op) {
|
||||
function close_reslov_dialog() {
|
||||
document.body.classList.remove('dialog-reslov-active');
|
||||
document.documentElement.style.overflowY = 'scroll';
|
||||
}
|
||||
|
||||
function reslov_container(op) {
|
||||
let s = document.getElementById(op + '-status');
|
||||
if (!s) return;
|
||||
let cmd_line = prompt("<%:Plese input <docker create/run> command line:%>", "");
|
||||
let cmd_line = document.getElementById("dialog_reslov_text").value;
|
||||
if (cmd_line == null || cmd_line == "") {
|
||||
s.innerHTML = "<font color='red'>Canceled</font>";
|
||||
s.innerHTML = "<font color='red'><%:Canceled%></font>";
|
||||
close_reslov_dialog()
|
||||
return;
|
||||
}
|
||||
if (! cmd_line.match("^docker")) {
|
||||
s.innerHTML = "<font color='red'>Command line Error</font>";
|
||||
if (!cmd_line.match(/^docker\s+(run|create)/)) {
|
||||
s.innerHTML = "<font color='red'><%:Command line Error%></font>";
|
||||
close_reslov_dialog()
|
||||
return;
|
||||
}
|
||||
let reg_space = /\s+/g
|
||||
let reg_muti_line= /\\\s*\n/g
|
||||
let reg_rem =/(?<!\\)`#.+(?<!\\)`/g // the command has `# `
|
||||
cmd_line = cmd_line.replace(reg_rem, " ").replace(reg_muti_line, " ").replace(reg_space, " ")
|
||||
console.log(cmd_line)
|
||||
window.location.href = "/cgi-bin/luci/admin/docker/newcontainer/" + encodeURI(cmd_line)
|
||||
}
|
||||
|
||||
function show_reslov_dialog(op) {
|
||||
document.getElementById('dialog_reslov') || document.body.insertAdjacentHTML("beforeend", '<div id="dialog_reslov"><div class="dialog_box"><div class="dialog_line"></div><div class="dialog_line"><h5><%:Plese input <docker create/run> command line:%></h5></div><div class="dialog_line"><textarea class="cbi-input-textarea" id="dialog_reslov_text" style="width: 100%; height:100%;" rows="15"></textarea></div><div class="dialog_line"><input type="button" class="cbi-button cbi-button-apply" type="submit" value="<%:Submit%>" onclick="reslov_container(\'' + op + '\')" /> <input type="button" class="cbi-button cbi-button-reset" type="reset" value="<%:Cancel%>" onclick="close_reslov_dialog()" /></div></div></div>')
|
||||
document.body.classList.add('dialog-reslov-active');
|
||||
document.documentElement.style.overflowY = 'hidden';
|
||||
}
|
||||
</script>
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Command line%>" onclick="resolv_container('<%=self.option%>')" />
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Command line%>"
|
||||
onclick="show_reslov_dialog('<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"></span>
|
||||
<%+cbi/valuefooter%>
|
||||
@ -324,3 +324,9 @@ msgstr "设备"
|
||||
|
||||
msgid "Finish Time"
|
||||
msgstr "结束时间"
|
||||
|
||||
msgid "Command line Error"
|
||||
msgstr "命令行错误"
|
||||
|
||||
msgid "Canceled"
|
||||
msgstr "已取消"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user