luci-app-dockerman: fix EOL issue
[oweals/luci.git] / applications / luci-app-dockerman / luasrc / model / cbi / dockerman / containers.lua
1 --[[
2 LuCI - Lua Configuration Interface
3 Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
4 ]]--
5
6 require "luci.util"
7 local http = require "luci.http"
8 local uci = luci.model.uci.cursor()
9 local docker = require "luci.model.docker"
10 local dk = docker.new()
11
12 local images, networks, containers
13 local res = dk.images:list()
14 if res.code <300 then images = res.body else return end
15 res = dk.networks:list()
16 if res.code <300 then networks = res.body else return end
17 res = dk.containers:list({query = {all=true}})
18 if res.code <300 then containers = res.body else return end
19
20 local urlencode = luci.http.protocol and luci.http.protocol.urlencode or luci.util.urlencode
21
22 function get_containers()
23   local data = {}
24   if type(containers) ~= "table" then return nil end
25   for i, v in ipairs(containers) do
26     local index = v.Created .. v.Id
27     data[index]={}
28     data[index]["_selected"] = 0
29     data[index]["_id"] = v.Id:sub(1,12)
30     data[index]["name"] = v.Names[1]:sub(2)
31     data[index]["_name"] = '<a href='..luci.dispatcher.build_url("admin/docker/container/"..v.Id)..'  class="dockerman_link" title="'..translate("Container detail")..'">'.. v.Names[1]:sub(2).."</a>"
32     data[index]["_status"] = v.Status
33     if v.Status:find("^Up") then
34       data[index]["_status"] = '<font color="green">'.. data[index]["_status"] .. "</font>"
35     else
36       data[index]["_status"] = '<font color="red">'.. data[index]["_status"] .. "</font>"
37     end
38     if (type(v.NetworkSettings) == "table" and type(v.NetworkSettings.Networks) == "table") then
39       for networkname, netconfig in pairs(v.NetworkSettings.Networks) do
40         data[index]["_network"] = (data[index]["_network"] ~= nil and (data[index]["_network"] .." | ") or "").. networkname .. (netconfig.IPAddress ~= "" and (": " .. netconfig.IPAddress) or "")
41       end
42     end
43     -- networkmode = v.HostConfig.NetworkMode ~= "default" and v.HostConfig.NetworkMode or "bridge"
44     -- data[index]["_network"] = v.NetworkSettings.Networks[networkmode].IPAddress or nil
45     -- local _, _, image = v.Image:find("^sha256:(.+)")
46     -- if image ~= nil then
47     --   image=image:sub(1,12)
48     -- end
49     if v.Ports and next(v.Ports) ~= nil then
50       data[index]["_ports"] = nil
51       for _,v2 in ipairs(v.Ports) do
52         data[index]["_ports"] = (data[index]["_ports"] and (data[index]["_ports"] .. ", ") or "")
53         .. ((v2.PublicPort and v2.Type and v2.Type == "tcp") and ('<a href="javascript:void(0);" onclick="window.open((window.location.origin.match(/^(.+):\\d+$/) && window.location.origin.match(/^(.+):\\d+$/)[1] || window.location.origin) + \':\' + '.. v2.PublicPort ..', \'_blank\');">') or "")
54         .. (v2.PublicPort and (v2.PublicPort .. ":") or "")  .. (v2.PrivatePort and (v2.PrivatePort .."/") or "") .. (v2.Type and v2.Type or "")
55         .. ((v2.PublicPort and v2.Type and v2.Type == "tcp")and "</a>" or "")
56       end
57     end
58     for ii,iv in ipairs(images) do
59       if iv.Id == v.ImageID then
60         data[index]["_image"] = iv.RepoTags and iv.RepoTags[1] or (iv.RepoDigests[1]:gsub("(.-)@.+", "%1") .. ":<none>")
61       end
62     end
63     
64     data[index]["_image_id"] = v.ImageID:sub(8,20)
65     data[index]["_command"] = v.Command
66   end
67   return data
68 end
69
70 local c_lists = get_containers()
71 -- list Containers
72 -- m = Map("docker", translate("Docker"))
73 m = SimpleForm("docker", translate("Docker"))
74 m.submit=false
75 m.reset=false
76
77 docker_status = m:section(SimpleSection)
78 docker_status.template = "dockerman/apply_widget"
79 docker_status.err=docker:read_status()
80 docker_status.err=docker_status.err and docker_status.err:gsub("\n","<br>"):gsub(" ","&nbsp;")
81 if docker_status.err then docker:clear_status() end
82
83 c_table = m:section(Table, c_lists, translate("Containers"))
84 c_table.nodescr=true
85 -- v.template = "cbi/tblsection"
86 -- v.sortable = true
87 container_selecter = c_table:option(Flag, "_selected","")
88 container_selecter.disabled = 0
89 container_selecter.enabled = 1
90 container_selecter.default = 0
91
92 container_id = c_table:option(DummyValue, "_id", translate("ID"))
93 container_id.width="10%"
94 container_name = c_table:option(DummyValue, "_name", translate("Container Name"))
95 container_name.rawhtml = true
96 container_status = c_table:option(DummyValue, "_status", translate("Status"))
97 container_status.width="15%"
98 container_status.rawhtml=true
99 container_ip = c_table:option(DummyValue, "_network", translate("Network"))
100 container_ip.width="15%"
101 container_ports = c_table:option(DummyValue, "_ports", translate("Ports"))
102 container_ports.width="10%"
103 container_ports.rawhtml = true
104 container_image = c_table:option(DummyValue, "_image", translate("Image"))
105 container_image.width="10%"
106 container_command = c_table:option(DummyValue, "_command", translate("Command"))
107 container_command.width="20%"
108
109 container_selecter.write=function(self, section, value)
110   c_lists[section]._selected = value
111 end
112
113 local start_stop_remove = function(m,cmd)
114   local c_selected = {}
115   -- 遍历table中sectionid
116   local c_table_sids = c_table:cfgsections()
117   for _, c_table_sid in ipairs(c_table_sids) do
118     -- 得到选中项的名字
119     if c_lists[c_table_sid]._selected == 1 then
120       c_selected[#c_selected+1] = c_lists[c_table_sid].name --container_name:cfgvalue(c_table_sid)
121     end
122   end
123   if #c_selected >0 then
124     docker:clear_status()
125     local success = true
126     for _,cont in ipairs(c_selected) do
127       docker:append_status("Containers: " .. cmd .. " " .. cont .. "...")
128       local res = dk.containers[cmd](dk, {id = cont})
129       if res and res.code >= 300 then
130         success = false
131         docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "\n")
132       else
133         docker:append_status("done\n")
134       end
135     end
136     if success then docker:clear_status() end
137     luci.http.redirect(luci.dispatcher.build_url("admin/docker/containers"))
138   end
139 end
140
141 action_section = m:section(Table,{{}})
142 action_section.notitle=true
143 action_section.rowcolors=false
144 action_section.template="cbi/nullsection"
145
146 btnnew=action_section:option(Button, "_new")
147 btnnew.inputtitle= translate("New")
148 btnnew.template = "dockerman/cbi/inlinebutton"
149 btnnew.inputstyle = "add"
150 btnnew.forcewrite = true
151 btnstart=action_section:option(Button, "_start")
152 btnstart.template = "dockerman/cbi/inlinebutton"
153 btnstart.inputtitle=translate("Start")
154 btnstart.inputstyle = "apply"
155 btnstart.forcewrite = true
156 btnrestart=action_section:option(Button, "_restart")
157 btnrestart.template = "dockerman/cbi/inlinebutton"
158 btnrestart.inputtitle=translate("Restart")
159 btnrestart.inputstyle = "reload"
160 btnrestart.forcewrite = true
161 btnstop=action_section:option(Button, "_stop")
162 btnstop.template = "dockerman/cbi/inlinebutton"
163 btnstop.inputtitle=translate("Stop")
164 btnstop.inputstyle = "reset"
165 btnstop.forcewrite = true
166 btnkill=action_section:option(Button, "_kill")
167 btnkill.template = "dockerman/cbi/inlinebutton"
168 btnkill.inputtitle=translate("Kill")
169 btnkill.inputstyle = "reset"
170 btnkill.forcewrite = true
171 btnremove=action_section:option(Button, "_remove")
172 btnremove.template = "dockerman/cbi/inlinebutton"
173 btnremove.inputtitle=translate("Remove")
174 btnremove.inputstyle = "remove"
175 btnremove.forcewrite = true
176 btnnew.write = function(self, section)
177   luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer"))
178 end
179 btnstart.write = function(self, section)
180   start_stop_remove(m,"start")
181 end
182 btnrestart.write = function(self, section)
183   start_stop_remove(m,"restart")
184 end
185 btnremove.write = function(self, section)
186   start_stop_remove(m,"remove")
187 end
188 btnstop.write = function(self, section)
189   start_stop_remove(m,"stop")
190 end
191 btnkill.write = function(self, section)
192   start_stop_remove(m,"kill")
193 end
194
195 return m