From b0259b559249c979698b9f59891399920bf81070 Mon Sep 17 00:00:00 2001 From: c0derMo Date: Thu, 13 Jan 2022 16:17:07 +0000 Subject: [PATCH 01/14] Added docker container monitor --- db/patch-add-docker-columns.sql | 10 ++++++++++ server/database.js | 1 + server/model/monitor.js | 23 +++++++++++++++++++++++ src/pages/EditMonitor.vue | 19 +++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 db/patch-add-docker-columns.sql diff --git a/db/patch-add-docker-columns.sql b/db/patch-add-docker-columns.sql new file mode 100644 index 00000000..fdde4170 --- /dev/null +++ b/db/patch-add-docker-columns.sql @@ -0,0 +1,10 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. +BEGIN TRANSACTION; + +ALTER TABLE monitor + ADD docker_daemon VARCHAR(255); + +ALTER TABLE monitor + ADD docker_container VARCHAR(255); + +COMMIT; diff --git a/server/database.js b/server/database.js index afcace70..536acd19 100644 --- a/server/database.js +++ b/server/database.js @@ -53,6 +53,7 @@ class Database { "patch-2fa-invalidate-used-token.sql": true, "patch-notification_sent_history.sql": true, "patch-monitor-basic-auth.sql": true, + "patch-add-docker-columns.sql": true } /** diff --git a/server/model/monitor.js b/server/model/monitor.js index c4441d63..5683352f 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -77,6 +77,8 @@ class Monitor extends BeanModel { dns_resolve_server: this.dns_resolve_server, dns_last_result: this.dns_last_result, pushToken: this.pushToken, + docker_container: this.docker_container, + docker_daemon: this.docker_daemon, notificationIDList, tags: tags, }; @@ -347,6 +349,27 @@ class Monitor extends BeanModel { throw new Error("Server not found on Steam"); } + } else if (this.type === "docker") { + debug(`[${this.name}] Prepare Options for axios`); + + const options = { + url: `/containers/${this.docker_container}/json`, + headers: { + "Accept": "*/*", + "User-Agent": "Uptime-Kuma/" + version, + }, + socketPath: this.docker_daemon, + httpsAgent: new https.Agent({ + maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) + rejectUnauthorized: ! this.getIgnoreTls(), + }), + }; + + debug(`[${this.name}] Axios Request`); + let res = await axios.request(options); + if (res.data.State.Running) { + bean.status = UP; + } } else { bean.msg = "Unknown Monitor Type"; bean.status = PENDING; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 4b6a920c..8b02a75f 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -32,6 +32,9 @@ + @@ -115,6 +118,20 @@ + + +
+ + +
+ + + +
+ + +
+
@@ -439,6 +456,8 @@ export default { accepted_statuscodes: ["200-299"], dns_resolve_type: "A", dns_resolve_server: "1.1.1.1", + docker_container: "", + docker_daemon: "/var/run/docker.sock" }; for (let i = 0; i < this.$root.notificationList.length; i++) { From c5cc42272f0a72dbbf7c971173ad54fe6a524bf5 Mon Sep 17 00:00:00 2001 From: c0derMo Date: Thu, 13 Jan 2022 18:28:45 +0000 Subject: [PATCH 02/14] Fixing the editing of docker container & adding english translation --- server/model/monitor.js | 1 + server/server.js | 2 ++ src/languages/en.js | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 5683352f..5e32a89d 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -369,6 +369,7 @@ class Monitor extends BeanModel { let res = await axios.request(options); if (res.data.State.Running) { bean.status = UP; + bean.msg = ""; } } else { bean.msg = "Unknown Monitor Type"; diff --git a/server/server.js b/server/server.js index 868bbd5e..7495cfb8 100644 --- a/server/server.js +++ b/server/server.js @@ -588,6 +588,8 @@ exports.entryPage = "dashboard"; bean.dns_resolve_type = monitor.dns_resolve_type; bean.dns_resolve_server = monitor.dns_resolve_server; bean.pushToken = monitor.pushToken; + bean.docker_container = monitor.docker_container; + bean.docker_daemon = monitor.docker_daemon; await R.store(bean); diff --git a/src/languages/en.js b/src/languages/en.js index 47513466..1d56e139 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -351,7 +351,7 @@ export default { serwersmsAPIPassword: "API Password", serwersmsPhoneNumber: "Phone number", serwersmsSenderName: "SMS Sender Name (registered via customer portal)", - "stackfield": "Stackfield", + stackfield: "Stackfield", smtpDkimSettings: "DKIM Settings", smtpDkimDesc: "Please refer to the Nodemailer DKIM {0} for usage.", documentation: "documentation", @@ -361,4 +361,6 @@ export default { smtpDkimHashAlgo: "Hash Algorithm (Optional)", smtpDkimheaderFieldNames: "Header Keys to sign (Optional)", smtpDkimskipFields: "Header Keys not to sign (Optional)", + "Container Name / ID": "Container Name / ID", + "Docker Daemon": "Docker Daemon", }; From 9619d31a05752d878de80d84679d0fec7fa2e117 Mon Sep 17 00:00:00 2001 From: c0derMo Date: Thu, 13 Jan 2022 18:33:01 +0000 Subject: [PATCH 03/14] Adding docker container ability to readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f88db5f..f2434b2d 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ VPS is sponsored by Uptime Kuma sponsors on [Open Collective](https://opencollec ## ⭐ Features -* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / Ping / DNS Record / Push / Steam Game Server. +* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / Ping / DNS Record / Push / Steam Game Server / Docker Containers. * Fancy, Reactive, Fast UI/UX. * Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [70+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications). * 20 second intervals. From 4818bb67d60075b67435922bc3d00236e0bc23ac Mon Sep 17 00:00:00 2001 From: c0derMo Date: Fri, 14 Jan 2022 09:09:37 +0000 Subject: [PATCH 04/14] Added trailing comma, fixed spelling & translation --- server/database.js | 2 +- server/model/monitor.js | 2 +- src/languages/en.js | 1 + src/pages/EditMonitor.vue | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/database.js b/server/database.js index 536acd19..69551bac 100644 --- a/server/database.js +++ b/server/database.js @@ -53,7 +53,7 @@ class Database { "patch-2fa-invalidate-used-token.sql": true, "patch-notification_sent_history.sql": true, "patch-monitor-basic-auth.sql": true, - "patch-add-docker-columns.sql": true + "patch-add-docker-columns.sql": true, } /** diff --git a/server/model/monitor.js b/server/model/monitor.js index 5e32a89d..b75500ec 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -350,7 +350,7 @@ class Monitor extends BeanModel { } } else if (this.type === "docker") { - debug(`[${this.name}] Prepare Options for axios`); + debug(`[${this.name}] Prepare Options for Axios`); const options = { url: `/containers/${this.docker_container}/json`, diff --git a/src/languages/en.js b/src/languages/en.js index 1d56e139..ae9fa526 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -363,4 +363,5 @@ export default { smtpDkimskipFields: "Header Keys not to sign (Optional)", "Container Name / ID": "Container Name / ID", "Docker Daemon": "Docker Daemon", + "Docker Container": "Docker Container", }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 8b02a75f..86c35ef0 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -33,7 +33,7 @@ Steam Game Server
@@ -457,7 +457,7 @@ export default { dns_resolve_type: "A", dns_resolve_server: "1.1.1.1", docker_container: "", - docker_daemon: "/var/run/docker.sock" + docker_daemon: "/var/run/docker.sock", }; for (let i = 0; i < this.$root.notificationList.length; i++) { From 29df70949d453dc4675eda05d7f107669e1fb3e1 Mon Sep 17 00:00:00 2001 From: c0derMo Date: Sat, 22 Jan 2022 01:57:37 +0000 Subject: [PATCH 05/14] Add ability to connect to daemon via http / tcp for windows compatibility --- db/patch-add-docker-columns.sql | 3 +++ server/model/monitor.js | 8 +++++++- server/server.js | 1 + src/languages/en.js | 3 +++ src/pages/EditMonitor.vue | 15 +++++++++++++++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/db/patch-add-docker-columns.sql b/db/patch-add-docker-columns.sql index fdde4170..56475667 100644 --- a/db/patch-add-docker-columns.sql +++ b/db/patch-add-docker-columns.sql @@ -7,4 +7,7 @@ ALTER TABLE monitor ALTER TABLE monitor ADD docker_container VARCHAR(255); +ALTER TABLE monitor + ADD docker_type VARCHAR(255); + COMMIT; diff --git a/server/model/monitor.js b/server/model/monitor.js index b75500ec..d8a4be23 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -79,6 +79,7 @@ class Monitor extends BeanModel { pushToken: this.pushToken, docker_container: this.docker_container, docker_daemon: this.docker_daemon, + docker_type: this.docker_type, notificationIDList, tags: tags, }; @@ -358,13 +359,18 @@ class Monitor extends BeanModel { "Accept": "*/*", "User-Agent": "Uptime-Kuma/" + version, }, - socketPath: this.docker_daemon, httpsAgent: new https.Agent({ maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) rejectUnauthorized: ! this.getIgnoreTls(), }), }; + if (this.docker_type === "socket") { + options.socketPath = this.docker_daemon; + } else if (this.docker_type === "tcp") { + options.baseURL = this.docker_daemon; + } + debug(`[${this.name}] Axios Request`); let res = await axios.request(options); if (res.data.State.Running) { diff --git a/server/server.js b/server/server.js index 7495cfb8..ac68769d 100644 --- a/server/server.js +++ b/server/server.js @@ -590,6 +590,7 @@ exports.entryPage = "dashboard"; bean.pushToken = monitor.pushToken; bean.docker_container = monitor.docker_container; bean.docker_daemon = monitor.docker_daemon; + bean.docker_type = monitor.docker_type; await R.store(bean); diff --git a/src/languages/en.js b/src/languages/en.js index ae9fa526..ade50373 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -364,4 +364,7 @@ export default { "Container Name / ID": "Container Name / ID", "Docker Daemon": "Docker Daemon", "Docker Container": "Docker Container", + "Docker Type": "Connection Type", + docker_socket: "Socket", + docker_tcp: "TCP / HTTP", }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 86c35ef0..b80b9a26 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -125,6 +125,20 @@ + + +
+ + +
+
@@ -458,6 +472,7 @@ export default { dns_resolve_server: "1.1.1.1", docker_container: "", docker_daemon: "/var/run/docker.sock", + docker_type: "socket", }; for (let i = 0; i < this.$root.notificationList.length; i++) { From 84a0b24448fc06f791bf4555fb2db8cd384c815b Mon Sep 17 00:00:00 2001 From: Moritz R Date: Sun, 3 Apr 2022 17:15:21 +0200 Subject: [PATCH 06/14] Update server/model/monitor.js As per recommendation of @Computroniks Co-authored-by: Matthew Nickson --- server/model/monitor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/model/monitor.js b/server/model/monitor.js index d8a4be23..c9b697d0 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -377,6 +377,7 @@ class Monitor extends BeanModel { bean.status = UP; bean.msg = ""; } + } else { bean.msg = "Unknown Monitor Type"; bean.status = PENDING; From 32cfd411f87ed98bd3247a7751b2f4791fbd388e Mon Sep 17 00:00:00 2001 From: c0derMo Date: Thu, 19 May 2022 12:35:55 +0000 Subject: [PATCH 07/14] Fixed style & code errors --- server/model/monitor.js | 4 ++-- src/pages/EditMonitor.vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index c7e2cd31..2bc40b5f 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -429,7 +429,7 @@ class Monitor extends BeanModel { throw new Error("Server not found on Steam"); } } else if (this.type === "docker") { - debug(`[${this.name}] Prepare Options for Axios`); + log.debug(`[${this.name}] Prepare Options for Axios`); const options = { url: `/containers/${this.docker_container}/json`, @@ -449,7 +449,7 @@ class Monitor extends BeanModel { options.baseURL = this.docker_daemon; } - debug(`[${this.name}] Axios Request`); + log.debug(`[${this.name}] Axios Request`); let res = await axios.request(options); if (res.data.State.Running) { bean.status = UP; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 56c9ac92..1d156883 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -120,7 +120,7 @@
- +
From 0d098b0958048ccf9503049a4436b9a4f758e4d8 Mon Sep 17 00:00:00 2001 From: c0derMo Date: Fri, 22 Jul 2022 15:47:04 +0000 Subject: [PATCH 08/14] Docker Hosts are now a table & have their own dialog --- db/patch-add-docker-columns.sql | 13 +- server/client.js | 20 +++ server/docker.js | 67 ++++++++ server/model/docker_host.js | 19 +++ server/model/monitor.js | 13 +- server/server.js | 8 +- .../socket-handlers/docker-socket-handler.js | 67 ++++++++ src/components/DockerHostDialog.vue | 160 ++++++++++++++++++ src/mixins/socket.js | 5 + src/pages/EditMonitor.vue | 44 +++-- 10 files changed, 385 insertions(+), 31 deletions(-) create mode 100644 server/docker.js create mode 100644 server/model/docker_host.js create mode 100644 server/socket-handlers/docker-socket-handler.js create mode 100644 src/components/DockerHostDialog.vue diff --git a/db/patch-add-docker-columns.sql b/db/patch-add-docker-columns.sql index 56475667..4cea448d 100644 --- a/db/patch-add-docker-columns.sql +++ b/db/patch-add-docker-columns.sql @@ -1,13 +1,18 @@ -- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; +CREATE TABLE docker_host ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + user_id INT NOT NULL, + docker_daemon VARCHAR(255), + docker_type VARCHAR(255), + name VARCHAR(255) +); + ALTER TABLE monitor - ADD docker_daemon VARCHAR(255); + ADD docker_host INTEGER REFERENCES docker_host(id); ALTER TABLE monitor ADD docker_container VARCHAR(255); -ALTER TABLE monitor - ADD docker_type VARCHAR(255); - COMMIT; diff --git a/server/client.js b/server/client.js index f6f133d1..61403842 100644 --- a/server/client.js +++ b/server/client.js @@ -122,10 +122,30 @@ async function sendInfo(socket) { }); } +async function sendDockerHostList(socket) { + const timeLogger = new TimeLogger(); + + let result = []; + let list = await R.find("docker_host", " user_id = ? ", [ + socket.userID, + ]); + + for (let bean of list) { + result.push(bean.export()); + } + + io.to(socket.userID).emit("dockerHostList", result); + + timeLogger.print("Send Docker Host List"); + + return list; +} + module.exports = { sendNotificationList, sendImportantHeartbeatList, sendHeartbeatList, sendProxyList, sendInfo, + sendDockerHostList }; diff --git a/server/docker.js b/server/docker.js new file mode 100644 index 00000000..a13236aa --- /dev/null +++ b/server/docker.js @@ -0,0 +1,67 @@ +const axios = require("axios"); +const { R } = require("redbean-node"); +const version = require("../package.json").version; +const https = require("https"); + +class DockerHost { + static async save(dockerHost, dockerHostID, userID) { + let bean; + + if (dockerHostID) { + bean = await R.findOne("docker_host", " id = ? AND user_id = ? ", [ dockerHostID, userID ]); + + if (!bean) { + throw new Error("docker host not found"); + } + + } else { + bean = R.dispense("docker_host"); + } + + bean.user_id = userID; + bean.docker_daemon = dockerHost.docker_daemon; + bean.docker_type = dockerHost.docker_type; + bean.name = dockerHost.name; + + await R.store(bean); + + return bean; + } + + static async delete(dockerHostID, userID) { + let bean = await R.findOne("docker_host", " id = ? AND user_id = ? ", [ dockerHostID, userID ]); + + if (!bean) { + throw new Error("docker host not found"); + } + + await R.trash(bean); + } + + static async getAmountContainer(dockerHost) { + const options = { + url: "/containers/json?all=true", + headers: { + "Accept": "*/*", + "User-Agent": "Uptime-Kuma/" + version + }, + httpsAgent: new https.Agent({ + maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) + rejectUnauthorized: false, + }), + }; + + if (dockerHost.docker_type === "socket") { + options.socketPath = dockerHost.docker_daemon; + } else if (dockerHost.docker_type === "tcp") { + options.baseURL = dockerHost.docker_daemon; + } + + let res = await axios.request(options); + return res.data.length; + } +} + +module.exports = { + DockerHost, +} \ No newline at end of file diff --git a/server/model/docker_host.js b/server/model/docker_host.js new file mode 100644 index 00000000..26f3035a --- /dev/null +++ b/server/model/docker_host.js @@ -0,0 +1,19 @@ +const { BeanModel } = require("redbean-node/dist/bean-model"); + +class DockerHost extends BeanModel { + /** + * Returns an object that ready to parse to JSON + * @returns {Object} + */ + toJSON() { + return { + id: this._id, + userId: this._user_id, + daemon: this._dockerDaemon, + type: this._dockerType, + name: this._name, + } + } +} + +module.exports = DockerHost; \ No newline at end of file diff --git a/server/model/monitor.js b/server/model/monitor.js index eff167c6..373796e9 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -89,8 +89,7 @@ class Monitor extends BeanModel { dns_last_result: this.dns_last_result, pushToken: this.pushToken, docker_container: this.docker_container, - docker_daemon: this.docker_daemon, - docker_type: this.docker_type, + docker_host: this.docker_host, proxyId: this.proxy_id, notificationIDList, tags: tags, @@ -471,6 +470,8 @@ class Monitor extends BeanModel { } else if (this.type === "docker") { log.debug(`[${this.name}] Prepare Options for Axios`); + const docker_host = await R.load("docker_host", this.docker_host); + const options = { url: `/containers/${this.docker_container}/json`, headers: { @@ -483,10 +484,10 @@ class Monitor extends BeanModel { }), }; - if (this.docker_type === "socket") { - options.socketPath = this.docker_daemon; - } else if (this.docker_type === "tcp") { - options.baseURL = this.docker_daemon; + if (docker_host._dockerType === "socket") { + options.socketPath = docker_host._dockerDaemon; + } else if (docker_host._dockerType === "tcp") { + options.baseURL = docker_host._dockerDaemon; } log.debug(`[${this.name}] Axios Request`); diff --git a/server/server.js b/server/server.js index 71a9a7b5..1e566148 100644 --- a/server/server.js +++ b/server/server.js @@ -118,13 +118,14 @@ if (config.demoMode) { } // Must be after io instantiation -const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList } = require("./client"); +const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList, sendDockerHostList } = require("./client"); const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler"); const databaseSocketHandler = require("./socket-handlers/database-socket-handler"); const TwoFA = require("./2fa"); const StatusPage = require("./model/status_page"); const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart, stop: cloudflaredStop } = require("./socket-handlers/cloudflared-socket-handler"); const { proxySocketHandler } = require("./socket-handlers/proxy-socket-handler"); +const { dockerSocketHandler } = require("./socket-handlers/docker-socket-handler"); app.use(express.json()); @@ -665,8 +666,7 @@ let needSetup = false; bean.dns_resolve_server = monitor.dns_resolve_server; bean.pushToken = monitor.pushToken; bean.docker_container = monitor.docker_container; - bean.docker_daemon = monitor.docker_daemon; - bean.docker_type = monitor.docker_type; + bean.docker_host = monitor.docker_host; bean.proxyId = Number.isInteger(monitor.proxyId) ? monitor.proxyId : null; bean.mqttUsername = monitor.mqttUsername; bean.mqttPassword = monitor.mqttPassword; @@ -1425,6 +1425,7 @@ let needSetup = false; cloudflaredSocketHandler(socket); databaseSocketHandler(socket); proxySocketHandler(socket); + dockerSocketHandler(socket); log.debug("server", "added all socket handlers"); @@ -1525,6 +1526,7 @@ async function afterLogin(socket, user) { let monitorList = await server.sendMonitorList(socket); sendNotificationList(socket); sendProxyList(socket); + sendDockerHostList(socket); await sleep(500); diff --git a/server/socket-handlers/docker-socket-handler.js b/server/socket-handlers/docker-socket-handler.js new file mode 100644 index 00000000..eddcd7b8 --- /dev/null +++ b/server/socket-handlers/docker-socket-handler.js @@ -0,0 +1,67 @@ +const { sendDockerHostList } = require("../client"); +const { checkLogin } = require("../util-server"); +const { DockerHost } = require("../docker"); + +module.exports.dockerSocketHandler = (socket) => { + socket.on("addDockerHost", async (dockerHost, dockerHostID, callback) => { + try { + checkLogin(socket); + + let dockerHostBean = await DockerHost.save(dockerHost, dockerHostID, socket.userID); + await sendDockerHostList(socket); + + callback({ + ok: true, + msg: "Saved", + id: dockerHostBean.id, + }); + + } catch (e) { + callback({ + ok: false, + msg: e.message, + }) + } + }); + + socket.on("deleteDockerHost", async (dockerHostID, callback) => { + try { + checkLogin(socket); + + await DockerHost.delete(dockerHostID, socket.userID); + await sendDockerHostList(socket); + + callback({ + ok: true, + msg: "Deleted", + }); + + } catch (e) { + callback({ + ok: false, + msg: e.message, + }) + } + }); + + socket.on("testDockerHost", async (dockerHost, callback) => { + try { + checkLogin(socket); + + let amount = await DockerHost.getAmountContainer(dockerHost); + + callback({ + ok: true, + msg: "Amount of containers: " + amount, + }); + + } catch (e) { + console.error(e); + + callback({ + ok: false, + msg: e.message, + }) + } + }) +} \ No newline at end of file diff --git a/src/components/DockerHostDialog.vue b/src/components/DockerHostDialog.vue new file mode 100644 index 00000000..e52c4ecf --- /dev/null +++ b/src/components/DockerHostDialog.vue @@ -0,0 +1,160 @@ + + + + + diff --git a/src/mixins/socket.js b/src/mixins/socket.js index c54b573f..f6de82c2 100644 --- a/src/mixins/socket.js +++ b/src/mixins/socket.js @@ -39,6 +39,7 @@ export default { uptimeList: { }, tlsInfoList: {}, notificationList: [], + dockerHostList: [], statusPageListLoaded: false, statusPageList: [], proxyList: [], @@ -141,6 +142,10 @@ export default { }); }); + socket.on("dockerHostList", (data) => { + this.dockerHostList = data; + }) + socket.on("heartbeat", (data) => { if (! (data.monitorID in this.heartbeatList)) { this.heartbeatList[data.monitorID] = []; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 60032459..5ff318bf 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -148,25 +148,25 @@
- +
- - -
+

{{ $t("Docker Host") }}

+

+ {{ $t("Not available, please setup.") }} +

- - -
- - +
+ + + {{ $t("Edit") }} +
+ +
@@ -446,6 +446,7 @@ + @@ -456,6 +457,7 @@ import VueMultiselect from "vue-multiselect"; import { useToast } from "vue-toastification"; import CopyableInput from "../components/CopyableInput.vue"; import NotificationDialog from "../components/NotificationDialog.vue"; +import DockerHostDialog from "../components/DockerHostDialog.vue"; import ProxyDialog from "../components/ProxyDialog.vue"; import TagsManager from "../components/TagsManager.vue"; import { genSecret, isDev } from "../util.ts"; @@ -467,6 +469,7 @@ export default { ProxyDialog, CopyableInput, NotificationDialog, + DockerHostDialog, TagsManager, VueMultiselect, }, @@ -625,8 +628,7 @@ export default { dns_resolve_type: "A", dns_resolve_server: "1.1.1.1", docker_container: "", - docker_daemon: "/var/run/docker.sock", - docker_type: "socket", + docker_host: null, proxyId: null, mqttUsername: "", mqttPassword: "", @@ -740,6 +742,12 @@ export default { addedProxy(id) { this.monitor.proxyId = id; }, + + // Added a Docker Host Event + // Enable it if the Docker Host is added in EditMonitor.vue + addedDockerHost(id) { + this.monitor.docker_host = id; + } }, }; From e356d5f62391fbcbaa523c291e2219372128ed7c Mon Sep 17 00:00:00 2001 From: c0derMo Date: Fri, 22 Jul 2022 15:57:40 +0000 Subject: [PATCH 09/14] Fixing linting & adding documentation --- server/client.js | 5 +++++ server/docker.js | 20 ++++++++++++++++++- server/model/docker_host.js | 4 ++-- server/model/monitor.js | 10 +++++----- .../socket-handlers/docker-socket-handler.js | 14 ++++++++----- src/components/DockerHostDialog.vue | 2 +- src/mixins/socket.js | 2 +- 7 files changed, 42 insertions(+), 15 deletions(-) diff --git a/server/client.js b/server/client.js index 61403842..bda77642 100644 --- a/server/client.js +++ b/server/client.js @@ -122,6 +122,11 @@ async function sendInfo(socket) { }); } +/** + * Send list of docker hosts to client + * @param {Socket} socket Socket.io socket instance + * @returns {Promise} + */ async function sendDockerHostList(socket) { const timeLogger = new TimeLogger(); diff --git a/server/docker.js b/server/docker.js index a13236aa..57e793ab 100644 --- a/server/docker.js +++ b/server/docker.js @@ -4,6 +4,13 @@ const version = require("../package.json").version; const https = require("https"); class DockerHost { + /** + * Save a docker host + * @param {Object} dockerHost Docker host to save + * @param {?number} dockerHostID ID of the docker host to update + * @param {number} userID ID of the user who adds the docker host + * @returns {Promise} + */ static async save(dockerHost, dockerHostID, userID) { let bean; @@ -28,6 +35,12 @@ class DockerHost { return bean; } + /** + * Delete a Docker host + * @param {number} dockerHostID ID of the Docker host to delete + * @param {number} userID ID of the user who created the Docker host + * @returns {Promise} + */ static async delete(dockerHostID, userID) { let bean = await R.findOne("docker_host", " id = ? AND user_id = ? ", [ dockerHostID, userID ]); @@ -38,6 +51,11 @@ class DockerHost { await R.trash(bean); } + /** + * Fetches the amount of containers on the Docker host + * @param {Object} dockerHost Docker host to check for + * @returns {number} Total amount of containers on the host + */ static async getAmountContainer(dockerHost) { const options = { url: "/containers/json?all=true", @@ -64,4 +82,4 @@ class DockerHost { module.exports = { DockerHost, -} \ No newline at end of file +}; diff --git a/server/model/docker_host.js b/server/model/docker_host.js index 26f3035a..229a9a52 100644 --- a/server/model/docker_host.js +++ b/server/model/docker_host.js @@ -12,8 +12,8 @@ class DockerHost extends BeanModel { daemon: this._dockerDaemon, type: this._dockerType, name: this._name, - } + }; } } -module.exports = DockerHost; \ No newline at end of file +module.exports = DockerHost; diff --git a/server/model/monitor.js b/server/model/monitor.js index 373796e9..babff876 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -470,7 +470,7 @@ class Monitor extends BeanModel { } else if (this.type === "docker") { log.debug(`[${this.name}] Prepare Options for Axios`); - const docker_host = await R.load("docker_host", this.docker_host); + const dockerHost = await R.load("docker_host", this.docker_host); const options = { url: `/containers/${this.docker_container}/json`, @@ -484,10 +484,10 @@ class Monitor extends BeanModel { }), }; - if (docker_host._dockerType === "socket") { - options.socketPath = docker_host._dockerDaemon; - } else if (docker_host._dockerType === "tcp") { - options.baseURL = docker_host._dockerDaemon; + if (dockerHost._dockerType === "socket") { + options.socketPath = dockerHost._dockerDaemon; + } else if (dockerHost._dockerType === "tcp") { + options.baseURL = dockerHost._dockerDaemon; } log.debug(`[${this.name}] Axios Request`); diff --git a/server/socket-handlers/docker-socket-handler.js b/server/socket-handlers/docker-socket-handler.js index eddcd7b8..7f3646bb 100644 --- a/server/socket-handlers/docker-socket-handler.js +++ b/server/socket-handlers/docker-socket-handler.js @@ -2,6 +2,10 @@ const { sendDockerHostList } = require("../client"); const { checkLogin } = require("../util-server"); const { DockerHost } = require("../docker"); +/** + * Handlers for docker hosts + * @param {Socket} socket Socket.io instance + */ module.exports.dockerSocketHandler = (socket) => { socket.on("addDockerHost", async (dockerHost, dockerHostID, callback) => { try { @@ -20,7 +24,7 @@ module.exports.dockerSocketHandler = (socket) => { callback({ ok: false, msg: e.message, - }) + }); } }); @@ -40,7 +44,7 @@ module.exports.dockerSocketHandler = (socket) => { callback({ ok: false, msg: e.message, - }) + }); } }); @@ -61,7 +65,7 @@ module.exports.dockerSocketHandler = (socket) => { callback({ ok: false, msg: e.message, - }) + }); } - }) -} \ No newline at end of file + }); +}; diff --git a/src/components/DockerHostDialog.vue b/src/components/DockerHostDialog.vue index e52c4ecf..d7cf2de0 100644 --- a/src/components/DockerHostDialog.vue +++ b/src/components/DockerHostDialog.vue @@ -66,7 +66,7 @@ export default { model: null, processing: false, id: null, - connectionTypes: ["socket", "tcp"], + connectionTypes: [ "socket", "tcp" ], dockerHost: { name: "", dockerDaemon: "", diff --git a/src/mixins/socket.js b/src/mixins/socket.js index f6de82c2..e2096b37 100644 --- a/src/mixins/socket.js +++ b/src/mixins/socket.js @@ -144,7 +144,7 @@ export default { socket.on("dockerHostList", (data) => { this.dockerHostList = data; - }) + }); socket.on("heartbeat", (data) => { if (! (data.monitorID in this.heartbeatList)) { From fb3b407577b5b2c9e9b8e6a45d53a6b32caf8d7b Mon Sep 17 00:00:00 2001 From: c0derMo Date: Sun, 24 Jul 2022 12:34:43 +0000 Subject: [PATCH 10/14] Added a settings page & localization --- server/docker.js | 3 ++ src/components/settings/Docker.vue | 50 ++++++++++++++++++++++++++++++ src/languages/en.js | 20 +++++++----- src/pages/EditMonitor.vue | 2 +- src/pages/Settings.vue | 3 ++ src/router.js | 5 +++ 6 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 src/components/settings/Docker.vue diff --git a/server/docker.js b/server/docker.js index 57e793ab..ed9e0854 100644 --- a/server/docker.js +++ b/server/docker.js @@ -48,6 +48,9 @@ class DockerHost { throw new Error("docker host not found"); } + // Delete removed proxy from monitors if exists + await R.exec("UPDATE monitor SET docker_host = null WHERE docker_host = ?", [ dockerHostID ]); + await R.trash(bean); } diff --git a/src/components/settings/Docker.vue b/src/components/settings/Docker.vue new file mode 100644 index 00000000..7b99bb8b --- /dev/null +++ b/src/components/settings/Docker.vue @@ -0,0 +1,50 @@ + + + \ No newline at end of file diff --git a/src/languages/en.js b/src/languages/en.js index 37392a4f..c7e4b377 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -372,12 +372,6 @@ export default { smtpDkimHashAlgo: "Hash Algorithm (Optional)", smtpDkimheaderFieldNames: "Header Keys to sign (Optional)", smtpDkimskipFields: "Header Keys not to sign (Optional)", - "Container Name / ID": "Container Name / ID", - "Docker Daemon": "Docker Daemon", - "Docker Container": "Docker Container", - "Docker Type": "Connection Type", - docker_socket: "Socket", - docker_tcp: "TCP / HTTP", wayToGetPagerDutyKey: "You can get this by going to Service -> Service Directory -> (Select a service) -> Integrations -> Add integration. Here you can search for \"Events API V2\". More info {0}", "Integration Key": "Integration Key", "Integration URL": "Integration URL", @@ -487,7 +481,7 @@ export default { "Leave blank to use a shared sender number.": "Leave blank to use a shared sender number.", "Octopush API Version": "Octopush API Version", "Legacy Octopush-DM": "Legacy Octopush-DM", - "endpoint": "endpoint", + endpoint: "endpoint", octopushAPIKey: "\"API key\" from HTTP API credentials in control panel", octopushLogin: "\"Login\" from HTTP API credentials in control panel", promosmsLogin: "API Login Name", @@ -531,7 +525,17 @@ export default { "Coming Soon": "Coming Soon", wayToGetClickSendSMSToken: "You can get API Username and API Key from {0} .", "Connection String": "Connection String", - "Query": "Query", + Query: "Query", settingsCertificateExpiry: "TLS Certificate Expiry", certificationExpiryDescription: "HTTPS Monitors trigger notification when TLS certificate expires in:", + "Setup Docker Host": "Setup Docker Host", + "Connection Type": "Connection Type", + "Docker Daemon": "Docker Daemon", + deleteDockerHostMsg: "Are you sure want to delete this docker host for all monitors?", + socket: "Socket", + tcp: "TCP / HTTP", + "Docker Container": "Docker Container", + "Container Name / ID": "Container Name / ID", + "Docker Host": "Docker Host", + "Docker Hosts": "Docker Hosts" }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 5ff318bf..c93fa97d 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -156,7 +156,7 @@ {{ $t("Not available, please setup.") }}

-
+
From f3322398e577c4ddf989daf12e2a366c6980d82b Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Fri, 29 Jul 2022 20:57:13 +0800 Subject: [PATCH 12/14] Fix and improve test docker host --- server/docker.js | 30 +++++++++++++++---- .../socket-handlers/docker-socket-handler.js | 14 +++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/server/docker.js b/server/docker.js index ed9e0854..1c939d64 100644 --- a/server/docker.js +++ b/server/docker.js @@ -59,7 +59,7 @@ class DockerHost { * @param {Object} dockerHost Docker host to check for * @returns {number} Total amount of containers on the host */ - static async getAmountContainer(dockerHost) { + static async testDockerHost(dockerHost) { const options = { url: "/containers/json?all=true", headers: { @@ -72,14 +72,32 @@ class DockerHost { }), }; - if (dockerHost.docker_type === "socket") { - options.socketPath = dockerHost.docker_daemon; - } else if (dockerHost.docker_type === "tcp") { - options.baseURL = dockerHost.docker_daemon; + if (dockerHost.dockerType === "socket") { + options.socketPath = dockerHost.dockerDaemon; + } else if (dockerHost.dockerType === "tcp") { + options.baseURL = dockerHost.dockerDaemon; } let res = await axios.request(options); - return res.data.length; + + if (Array.isArray(res.data)) { + + if (res.data.length > 1) { + + if ("ImageID" in res.data[0]) { + return res.data.length; + } else { + throw new Error("Invalid Docker response, is it Docker really a daemon?"); + } + + } else { + return res.data.length; + } + + } else { + throw new Error("Invalid Docker response, is it Docker really a daemon?"); + } + } } diff --git a/server/socket-handlers/docker-socket-handler.js b/server/socket-handlers/docker-socket-handler.js index 7f3646bb..5a53494d 100644 --- a/server/socket-handlers/docker-socket-handler.js +++ b/server/socket-handlers/docker-socket-handler.js @@ -1,6 +1,7 @@ const { sendDockerHostList } = require("../client"); const { checkLogin } = require("../util-server"); const { DockerHost } = require("../docker"); +const { log } = require("../../src/util"); /** * Handlers for docker hosts @@ -52,15 +53,22 @@ module.exports.dockerSocketHandler = (socket) => { try { checkLogin(socket); - let amount = await DockerHost.getAmountContainer(dockerHost); + let amount = await DockerHost.testDockerHost(dockerHost); + let msg; + + if (amount > 1) { + msg = "Connected Successfully. Amount of containers: " + amount; + } else { + msg = "Connected Successfully, but there are no containers?"; + } callback({ ok: true, - msg: "Amount of containers: " + amount, + msg, }); } catch (e) { - console.error(e); + log.error("docker", e); callback({ ok: false, From 8ced61697aea943aa0e25ff52f6b705715614242 Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Sat, 30 Jul 2022 19:48:12 +0800 Subject: [PATCH 13/14] Fix save docker host issue --- server/client.js | 2 +- server/docker.js | 4 ++-- server/model/docker_host.js | 10 +++++----- src/components/DockerHostDialog.vue | 11 ++++++++++- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/server/client.js b/server/client.js index 69892e66..a0c52e1e 100644 --- a/server/client.js +++ b/server/client.js @@ -139,7 +139,7 @@ async function sendDockerHostList(socket) { ]); for (let bean of list) { - result.push(bean.export()); + result.push(bean.toJSON()); } io.to(socket.userID).emit("dockerHostList", result); diff --git a/server/docker.js b/server/docker.js index 1c939d64..177fa6cb 100644 --- a/server/docker.js +++ b/server/docker.js @@ -26,8 +26,8 @@ class DockerHost { } bean.user_id = userID; - bean.docker_daemon = dockerHost.docker_daemon; - bean.docker_type = dockerHost.docker_type; + bean.docker_daemon = dockerHost.dockerDaemon; + bean.docker_type = dockerHost.dockerType; bean.name = dockerHost.name; await R.store(bean); diff --git a/server/model/docker_host.js b/server/model/docker_host.js index 229a9a52..20598292 100644 --- a/server/model/docker_host.js +++ b/server/model/docker_host.js @@ -7,11 +7,11 @@ class DockerHost extends BeanModel { */ toJSON() { return { - id: this._id, - userId: this._user_id, - daemon: this._dockerDaemon, - type: this._dockerType, - name: this._name, + id: this.id, + userID: this.user_id, + dockerDaemon: this.docker_daemon, + dockerType: this.docker_type, + name: this.name, }; } } diff --git a/src/components/DockerHostDialog.vue b/src/components/DockerHostDialog.vue index d7cf2de0..681cc244 100644 --- a/src/components/DockerHostDialog.vue +++ b/src/components/DockerHostDialog.vue @@ -52,8 +52,9 @@