diff --git a/README.md b/README.md index 1b4c885d0c..4311e1c617 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 0000000000..319d9048ec --- /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 da0c0d5c85..7ea2b37ded 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 db58ae8291..53fd5a5eb4 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 5d999b597c..f837b44854 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -42,6 +42,9 @@ +