dashboard.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import { Readable } from 'stream';
  2. import { Permission, Container } from '../database/models.js';
  3. import { modal } from '../components/modal.js';
  4. import { permissionsModal } from '../components/permissions_modal.js';
  5. import { setEvent, cpu, ram, tx, rx, disk, docker } from '../server.js';
  6. import { dockerContainerStats } from 'systeminformation';
  7. import { containerCard } from '../components/containerCard.js';
  8. let [ hidden, cardList, sentList ] = [ '', '', ''];
  9. export const Dashboard = (req, res) => {
  10. res.render("dashboard", {
  11. name: req.session.user,
  12. role: req.session.role,
  13. avatar: req.session.avatar,
  14. });
  15. }
  16. export const Start = (req, res) => {
  17. let name = req.header('hx-trigger-name');
  18. let state = req.header('hx-trigger');
  19. if (state == 'stopped') {
  20. var containerName = docker.getContainer(name);
  21. containerName.start();
  22. } else if (state == 'paused') {
  23. var containerName = docker.getContainer(name);
  24. containerName.unpause();
  25. }
  26. res.send("ok");
  27. }
  28. export const Stop = (req, res) => {
  29. let name = req.header('hx-trigger-name');
  30. let state = req.header('hx-trigger');
  31. if (state != 'stopped') {
  32. var containerName = docker.getContainer(name);
  33. containerName.stop();
  34. }
  35. res.send("ok");
  36. }
  37. export const Pause = (req, res) => {
  38. let name = req.header('hx-trigger-name');
  39. let state = req.header('hx-trigger');
  40. if (state == 'running') {
  41. var containerName = docker.getContainer(name);
  42. containerName.pause();
  43. } else if (state == 'paused') {
  44. var containerName = docker.getContainer(name);
  45. containerName.unpause();
  46. }
  47. res.send("ok");
  48. }
  49. export const Restart = (req, res) => {
  50. let name = req.header('hx-trigger-name');
  51. var containerName = docker.getContainer(name);
  52. containerName.restart();
  53. res.send("ok");
  54. }
  55. export const Logs = (req, res) => {
  56. let name = req.header('hx-trigger-name');
  57. function containerLogs (data) {
  58. return new Promise((resolve, reject) => {
  59. let logString = '';
  60. var options = {
  61. follow: false,
  62. stdout: true,
  63. stderr: false,
  64. timestamps: false
  65. };
  66. var containerName = docker.getContainer(data);
  67. containerName.logs(options, function (err, stream) {
  68. if (err) { reject(err); return; }
  69. const readableStream = Readable.from(stream);
  70. readableStream.on('data', function (chunk) {
  71. logString += chunk.toString('utf8');
  72. });
  73. readableStream.on('end', function () {
  74. resolve(logString);
  75. });
  76. });
  77. });
  78. };
  79. containerLogs(name).then((data) => {
  80. res.send(`<pre>${data}</pre> `)
  81. });
  82. }
  83. export const Modal = async (req, res) => {
  84. let name = req.header('hx-trigger-name');
  85. let id = req.header('hx-trigger');
  86. if (id == 'permissions') {
  87. let containerPermissions = await Permission.findAll({ where: {containerName: name}});
  88. let form = permissionsModal();
  89. res.send(form);
  90. return;
  91. }
  92. let containerId = docker.getContainer(name);
  93. let containerInfo = await containerId.inspect();
  94. let ports_list = [];
  95. try {
  96. for (const [key, value] of Object.entries(containerInfo.HostConfig.PortBindings)) {
  97. let ports = {
  98. check: 'checked',
  99. external: value[0].HostPort,
  100. internal: key.split('/')[0],
  101. protocol: key.split('/')[1]
  102. }
  103. ports_list.push(ports);
  104. }
  105. } catch {}
  106. let external_port = ports_list[0]?.external || 0;
  107. let internal_port = ports_list[0]?.internal || 0;
  108. let container_info = {
  109. name: containerInfo.Name.slice(1),
  110. state: containerInfo.State.Status,
  111. image: containerInfo.Config.Image,
  112. external_port: external_port,
  113. internal_port: internal_port,
  114. ports: ports_list,
  115. link: 'localhost',
  116. }
  117. let form = modal(container_info);
  118. res.send(form);
  119. }
  120. export const Stats = async (req, res) => {
  121. let name = req.header('hx-trigger-name');
  122. let color = req.header('hx-trigger');
  123. let value = 0;
  124. switch (name) {
  125. case 'CPU': value = cpu;
  126. break;
  127. case 'RAM': value = ram;
  128. break;
  129. case 'TX': value = tx;
  130. break;
  131. case 'RX': value = rx;
  132. break;
  133. case 'DISK': value = disk;
  134. break;
  135. }
  136. let info = `<div class="font-weight-medium">
  137. <label class="cpu-text mb-1">${name} ${value}%</label>
  138. </div>
  139. <div class="cpu-bar meter animate ${color}">
  140. <span style="width:${value}%"><span></span></span>
  141. </div>`;
  142. res.send(info);
  143. }
  144. export const Hide = async (req, res) => {
  145. let name = req.header('hx-trigger-name');
  146. let exists = await Container.findOne({ where: {name: name}});
  147. if (!exists) {
  148. const newContainer = await Container.create({ name: name, visibility: false, });
  149. } else {
  150. exists.update({ visibility: false });
  151. }
  152. setEvent(true, 'docker');
  153. res.send("ok");
  154. }
  155. export const Reset = async (req, res) => {
  156. Container.update({ visibility: true }, { where: {} });
  157. setEvent(true, 'docker');
  158. res.send("ok");
  159. }
  160. let stats = {};
  161. export const Chart = async (req, res) => {
  162. let name = req.header('hx-trigger-name');
  163. // create an empty array if it doesn't exist
  164. if (!stats[name]) {
  165. stats[name] = { cpuArray: Array(15).fill(0), ramArray: Array(15).fill(0) };
  166. }
  167. // get the stats
  168. const info = await dockerContainerStats(name);
  169. // update the arrays
  170. stats[name].cpuArray.push(Math.round(info[0].cpuPercent));
  171. stats[name].ramArray.push(Math.round(info[0].memPercent));
  172. // slice them down to the last 15 values
  173. stats[name].cpuArray = stats[name].cpuArray.slice(-15);
  174. stats[name].ramArray = stats[name].ramArray.slice(-15);
  175. // replace the chart with the new data
  176. let chart = `
  177. <script>
  178. ${name}chart.updateSeries([{
  179. data: [${stats[name].cpuArray}]
  180. }, {
  181. data: [${stats[name].ramArray}]
  182. }])
  183. </script>`
  184. res.send(chart);
  185. }
  186. export const Installing = (req, res) => {
  187. let install_info = {
  188. name: 'App Name',
  189. service: '',
  190. id: '',
  191. state: 'Installing',
  192. image: '',
  193. external_port: 0,
  194. internal_port: 0,
  195. ports: '',
  196. link: 'localhost',
  197. }
  198. let card = containerCard(install_info);
  199. res.send(card);
  200. }
  201. // Get hidden containers
  202. async function getHidden() {
  203. hidden = await Container.findAll({ where: {visibility:false}});
  204. hidden = hidden.map((container) => container.name);
  205. }
  206. // Create list of docker containers cards
  207. async function containerCards() {
  208. let list = '';
  209. const allContainers = await docker.listContainers({ all: true });
  210. for (const container of allContainers) {
  211. if (!hidden.includes(container.Names[0].slice(1))) {
  212. let imageVersion = container.Image.split('/');
  213. let service = imageVersion[imageVersion.length - 1].split(':')[0];
  214. let containerId = docker.getContainer(container.Id);
  215. let containerInfo = await containerId.inspect();
  216. let ports_list = [];
  217. try {
  218. for (const [key, value] of Object.entries(containerInfo.HostConfig.PortBindings)) {
  219. let ports = {
  220. check: 'checked',
  221. external: value[0].HostPort,
  222. internal: key.split('/')[0],
  223. protocol: key.split('/')[1]
  224. }
  225. ports_list.push(ports);
  226. }
  227. } catch {}
  228. let external_port = ports_list[0]?.external || 0;
  229. let internal_port = ports_list[0]?.internal || 0;
  230. let container_info = {
  231. name: container.Names[0].slice(1),
  232. service: service,
  233. id: container.Id,
  234. state: container.State,
  235. image: container.Image,
  236. external_port: external_port,
  237. internal_port: internal_port,
  238. ports: ports_list,
  239. link: 'localhost',
  240. }
  241. let card = containerCard(container_info);
  242. list += card;
  243. }
  244. }
  245. cardList = list;
  246. }
  247. export async function sendCheck() {
  248. await getHidden();
  249. await containerCards();
  250. if (cardList != sentList) {
  251. cardList = sentList;
  252. return true;
  253. } else {
  254. return false;
  255. }
  256. }
  257. export const Containers = async (req, res) => {
  258. await getHidden();
  259. await containerCards();
  260. sentList = cardList;
  261. res.send(cardList);
  262. }