From bd719d9987ef1c8b6775f76967526f3d7795c80e Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Fri, 18 Oct 2024 01:01:09 -0400 Subject: [PATCH] GH-5214: feat: Add Docker service availability monitoring Introduces Docker service availability to monitor uptime and status of Docker services alongside existing types. Updates the database schema to support "docker_service". Enhances the user interface to allow configuration of Docker service parameters within the monitor setup. This change allows for more granular monitoring capabilities by checking the running state of services in a Docker environment. Relates to implementing extended Docker monitoring functionalities. implements #5214 Signed-off-by: Bryan Gonzalez --- README.md | 2 +- .../2024-10-17-0000-add-docker-service.js | 11 +++++ server/model/monitor.js | 49 +++++++++++++++++++ server/server.js | 1 + src/pages/EditMonitor.vue | 15 +++++- 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 db/knex_migrations/2024-10-17-0000-add-docker-service.js diff --git a/README.md b/README.md index 1b4c885d0..4311e1c61 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Sponsore ## ⭐ Features -- Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers +- Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers / Docker Services - Fancy, Reactive, Fast UI/UX - Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications) - 20-second intervals diff --git a/db/knex_migrations/2024-10-17-0000-add-docker-service.js b/db/knex_migrations/2024-10-17-0000-add-docker-service.js new file mode 100644 index 000000000..319d9048e --- /dev/null +++ b/db/knex_migrations/2024-10-17-0000-add-docker-service.js @@ -0,0 +1,11 @@ +exports.up = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.string("docker_service", 255); + }); +}; + +exports.down = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.dropColumn("docker_service"); + }); +}; diff --git a/server/model/monitor.js b/server/model/monitor.js index da0c0d5c8..3ed269586 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -120,6 +120,7 @@ class Monitor extends BeanModel { dns_resolve_server: this.dns_resolve_server, dns_last_result: this.dns_last_result, docker_container: this.docker_container, + docker_service: this.docker_service, docker_host: this.docker_host, proxyId: this.proxy_id, notificationIDList: preloadData.notifications.get(this.id) || {}, @@ -754,6 +755,54 @@ class Monitor extends BeanModel { } else { throw Error("Container State is " + res.data.State.Status); } + } else if (this.type === "docker-service-availability") { // TODO: add a service-health to count running vs desired (needs services api) + log.debug("monitor", `[${this.name}] Prepare Options for Axios`); + + const options = { + url: `/tasks?filters={"service":{"${this.docker_service}":true}}`, + timeout: this.interval * 1000 * 0.8, + headers: { + "Accept": "*/*", + }, + httpsAgent: new https.Agent({ + maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) + rejectUnauthorized: !this.getIgnoreTls(), + secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT, + }), + httpAgent: new http.Agent({ + maxCachedSessions: 0, + }), + }; + + const dockerHost = await R.load("docker_host", this.docker_host); + + if (!dockerHost) { + throw new Error("Failed to load docker host config"); + } + + if (dockerHost._dockerType === "socket") { + options.socketPath = dockerHost._dockerDaemon; + } else if (dockerHost._dockerType === "tcp") { + options.baseURL = DockerHost.patchDockerURL(dockerHost._dockerDaemon); + options.httpsAgent = new https.Agent( + DockerHost.getHttpsAgentOptions(dockerHost._dockerType, options.baseURL) + ); + } + + log.debug("monitor", `[${this.name}] Axios Request (get service tasks)`); + let res = await axios.request(options); + + if (res.data.message) { + throw Error(res.data.message); + } + + if (res.data.filter((task) => task.Status.State === "running").length) { + bean.status = UP; + bean.msg = `Service: ${this.docker_service} is available`; + } else { + bean.status = DOWN; + bean.msg = `Service: ${this.docker_service} is Down. No replicas available`; + } } else if (this.type === "sqlserver") { let startTime = dayjs().valueOf(); diff --git a/server/server.js b/server/server.js index db58ae829..53fd5a5eb 100644 --- a/server/server.js +++ b/server/server.js @@ -826,6 +826,7 @@ let needSetup = false; bean.dns_resolve_server = monitor.dns_resolve_server; bean.pushToken = monitor.pushToken; bean.docker_container = monitor.docker_container; + bean.docker_service = monitor.docker_service; bean.docker_host = monitor.docker_host; bean.proxyId = Number.isInteger(monitor.proxyId) ? monitor.proxyId : null; bean.mqttUsername = monitor.mqttUsername; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 5d999b597..cc34e773a 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -42,6 +42,9 @@ +