containers.lua 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. --[[
  2. LuCI - Lua Configuration Interface
  3. Copyright 2019 lisaac <https://github.com/lisaac/luci-app-dockerman>
  4. ]]--
  5. local http = require "luci.http"
  6. local docker = require "luci.model.docker"
  7. local m, s, o
  8. local images, networks, containers, res
  9. local dk = docker.new()
  10. res = dk.images:list()
  11. if res.code <300 then
  12. images = res.body
  13. else
  14. return
  15. end
  16. res = dk.networks:list()
  17. if res.code <300 then
  18. networks = res.body
  19. else
  20. return
  21. end
  22. res = dk.containers:list({
  23. query = {
  24. all=true
  25. }
  26. })
  27. if res.code <300 then
  28. containers = res.body
  29. else
  30. return
  31. end
  32. local urlencode = luci.http.protocol and luci.http.protocol.urlencode or luci.util.urlencode
  33. function get_containers()
  34. local data = {}
  35. if type(containers) ~= "table" then
  36. return nil
  37. end
  38. for i, v in ipairs(containers) do
  39. local index = v.Id
  40. data[index]={}
  41. data[index]["_selected"] = 0
  42. data[index]["_id"] = v.Id:sub(1,12)
  43. data[index]["_name"] = v.Names[1]:sub(2)
  44. data[index]["_status"] = v.Status
  45. if v.Status:find("^Up") then
  46. data[index]["_status"] = '<font color="green">'.. data[index]["_status"] .. "</font>"
  47. else
  48. data[index]["_status"] = '<font color="red">'.. data[index]["_status"] .. "</font>"
  49. end
  50. if (type(v.NetworkSettings) == "table" and type(v.NetworkSettings.Networks) == "table") then
  51. for networkname, netconfig in pairs(v.NetworkSettings.Networks) do
  52. data[index]["_network"] = (data[index]["_network"] ~= nil and (data[index]["_network"] .." | ") or "").. networkname .. (netconfig.IPAddress ~= "" and (": " .. netconfig.IPAddress) or "")
  53. end
  54. end
  55. if v.Ports and next(v.Ports) ~= nil then
  56. data[index]["_ports"] = nil
  57. for _,v2 in ipairs(v.Ports) do
  58. data[index]["_ports"] = (data[index]["_ports"] and (data[index]["_ports"] .. ", ") or "")
  59. .. ((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 "")
  60. .. (v2.PublicPort and (v2.PublicPort .. ":") or "") .. (v2.PrivatePort and (v2.PrivatePort .."/") or "") .. (v2.Type and v2.Type or "")
  61. .. ((v2.PublicPort and v2.Type and v2.Type == "tcp")and "</a>" or "")
  62. end
  63. end
  64. for ii,iv in ipairs(images) do
  65. if iv.Id == v.ImageID then
  66. data[index]["_image"] = iv.RepoTags and iv.RepoTags[1] or (iv.RepoDigests[1]:gsub("(.-)@.+", "%1") .. ":<none>")
  67. end
  68. end
  69. data[index]["_image_id"] = v.ImageID:sub(8,20)
  70. data[index]["_command"] = v.Command
  71. end
  72. return data
  73. end
  74. local container_list = get_containers()
  75. m = SimpleForm("docker",
  76. translate("Docker - Containers"),
  77. translate("This page displays all containers that have been created on the connected docker host."))
  78. m.submit=false
  79. m.reset=false
  80. s = m:section(SimpleSection)
  81. s.template = "dockerman/apply_widget"
  82. s.err=docker:read_status()
  83. s.err=s.err and s.err:gsub("\n","<br />"):gsub(" ","&#160;")
  84. if s.err then
  85. docker:clear_status()
  86. end
  87. s = m:section(Table, container_list, translate("Containers overview"))
  88. s.addremove = false
  89. s.sectionhead = translate("Containers")
  90. s.sortable = false
  91. s.template = "cbi/tblsection"
  92. s.extedit = luci.dispatcher.build_url("admin", "docker", "container","%s")
  93. o = s:option(Flag, "_selected","")
  94. o.disabled = 0
  95. o.enabled = 1
  96. o.default = 0
  97. o.write=function(self, section, value)
  98. container_list[section]._selected = value
  99. end
  100. o = s:option(DummyValue, "_id", translate("ID"))
  101. o.width="10%"
  102. o = s:option(DummyValue, "_name", translate("Container Name"))
  103. o.rawhtml = true
  104. o = s:option(DummyValue, "_status", translate("Status"))
  105. o.width="15%"
  106. o.rawhtml=true
  107. o = s:option(DummyValue, "_network", translate("Network"))
  108. o.width="15%"
  109. o = s:option(DummyValue, "_ports", translate("Ports"))
  110. o.width="10%"
  111. o.rawhtml = true
  112. o = s:option(DummyValue, "_image", translate("Image"))
  113. o.width="10%"
  114. o = s:option(DummyValue, "_command", translate("Command"))
  115. o.width="20%"
  116. local start_stop_remove = function(m,cmd)
  117. local container_selected = {}
  118. for k in pairs(container_list) do
  119. if container_list[k]._selected == 1 then
  120. container_selected[#container_selected + 1] = container_list[k]._name
  121. end
  122. end
  123. if #container_selected > 0 then
  124. local success = true
  125. docker:clear_status()
  126. for _, cont in ipairs(container_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
  137. docker:clear_status()
  138. end
  139. luci.http.redirect(luci.dispatcher.build_url("admin/docker/containers"))
  140. end
  141. end
  142. s = m:section(Table,{{}})
  143. s.notitle=true
  144. s.rowcolors=false
  145. s.template="cbi/nullsection"
  146. o = s:option(Button, "_new")
  147. o.inputtitle= translate("Add")
  148. o.template = "dockerman/cbi/inlinebutton"
  149. o.inputstyle = "add"
  150. o.forcewrite = true
  151. o.write = function(self, section)
  152. luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer"))
  153. end
  154. o = s:option(Button, "_start")
  155. o.template = "dockerman/cbi/inlinebutton"
  156. o.inputtitle=translate("Start")
  157. o.inputstyle = "apply"
  158. o.forcewrite = true
  159. o.write = function(self, section)
  160. start_stop_remove(m,"start")
  161. end
  162. o = s:option(Button, "_restart")
  163. o.template = "dockerman/cbi/inlinebutton"
  164. o.inputtitle=translate("Restart")
  165. o.inputstyle = "reload"
  166. o.forcewrite = true
  167. o.write = function(self, section)
  168. start_stop_remove(m,"restart")
  169. end
  170. o = s:option(Button, "_stop")
  171. o.template = "dockerman/cbi/inlinebutton"
  172. o.inputtitle=translate("Stop")
  173. o.inputstyle = "reset"
  174. o.forcewrite = true
  175. o.write = function(self, section)
  176. start_stop_remove(m,"stop")
  177. end
  178. o = s:option(Button, "_kill")
  179. o.template = "dockerman/cbi/inlinebutton"
  180. o.inputtitle=translate("Kill")
  181. o.inputstyle = "reset"
  182. o.forcewrite = true
  183. o.write = function(self, section)
  184. start_stop_remove(m,"kill")
  185. end
  186. o = s:option(Button, "_remove")
  187. o.template = "dockerman/cbi/inlinebutton"
  188. o.inputtitle=translate("Remove")
  189. o.inputstyle = "remove"
  190. o.forcewrite = true
  191. o.write = function(self, section)
  192. start_stop_remove(m,"remove")
  193. end
  194. return m