From 99b2ba8944f1927da0a371d6a4bda05d0da9b736 Mon Sep 17 00:00:00 2001 From: Ivan Bravo Bravo Date: Wed, 26 Oct 2022 00:12:46 -0500 Subject: [PATCH 1/5] added basic support for Docker Swarm services --- src/pages/api/docker/stats/[...service].js | 37 +++++++++++++++++---- src/pages/api/docker/status/[...service].js | 35 +++++++++++++++---- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/src/pages/api/docker/stats/[...service].js b/src/pages/api/docker/stats/[...service].js index ca8c8bd3a..c16eeb58e 100644 --- a/src/pages/api/docker/stats/[...service].js +++ b/src/pages/api/docker/stats/[...service].js @@ -31,18 +31,41 @@ export default async function handler(req, res) { const containerNames = containers.map((container) => container.Names[0].replace(/^\//, "")); const containerExists = containerNames.includes(containerName); - if (!containerExists) { - res.status(200).send({ - error: "not found", + if (containerExists) { + const container = docker.getContainer(containerName); + const stats = await container.stats({ stream: false }); + + res.status(200).json({ + stats, }); return; } - const container = docker.getContainer(containerName); - const stats = await container.stats({ stream: false }); + // Try with a service deployed in Docker Swarm + const tasks = await docker.listTasks({ + filters: { + service: [containerName], + // A service can have several offline containers, so we only look for an active one. + 'desired-state': ['running'] + } + }).catch(() => []); + + // For now we are only interested in the first one (in case replicas > 1). + // TODO: Show the result for all replicas/containers? + const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID + + if (taskContainerId) { + const container = docker.getContainer(taskContainerId); + const stats = await container.stats({ stream: false }); + + res.status(200).json({ + stats, + }); + return; + } - res.status(200).json({ - stats, + res.status(200).send({ + error: "not found", }); } catch { res.status(500).send({ diff --git a/src/pages/api/docker/status/[...service].js b/src/pages/api/docker/status/[...service].js index 8330ac3d3..cc0f56759 100644 --- a/src/pages/api/docker/status/[...service].js +++ b/src/pages/api/docker/status/[...service].js @@ -29,17 +29,38 @@ export default async function handler(req, res) { const containerNames = containers.map((container) => container.Names[0].replace(/^\//, "")); const containerExists = containerNames.includes(containerName); - if (!containerExists) { - return res.status(200).send({ - error: "not found", + if (containerExists) { + const container = docker.getContainer(containerName); + const info = await container.inspect(); + + return res.status(200).json({ + status: info.State.Status, }); } - const container = docker.getContainer(containerName); - const info = await container.inspect(); + const tasks = await docker.listTasks({ + filters: { + service: [containerName], + // A service can have several offline containers, we only look for an active one. + 'desired-state': ['running'] + } + }).catch(() => []); + + // For now we are only interested in the first one (in case replicas > 1). + // TODO: Show the result for all replicas/containers? + const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID + + if (taskContainerId) { + const container = docker.getContainer(taskContainerId); + const info = await container.inspect(); + + return res.status(200).json({ + status: info.State.Status, + }); + } - return res.status(200).json({ - status: info.State.Status, + return res.status(200).send({ + error: "not found", }); } catch { return res.status(500).send({ From fb883c7b27610ccd50dfe3b31db2962b93c7e7db Mon Sep 17 00:00:00 2001 From: Vinay Dawani Date: Sun, 11 Dec 2022 03:03:20 -0500 Subject: [PATCH 2/5] added yaml file variable for swarm mode checks --- src/pages/api/docker/stats/[...service].js | 42 +++++++++++---------- src/pages/api/docker/status/[...service].js | 42 +++++++++++---------- src/utils/config/docker.js | 4 +- src/utils/config/service-helpers.js | 4 +- 4 files changed, 50 insertions(+), 42 deletions(-) diff --git a/src/pages/api/docker/stats/[...service].js b/src/pages/api/docker/stats/[...service].js index f5212aa6c..0258bc68d 100644 --- a/src/pages/api/docker/stats/[...service].js +++ b/src/pages/api/docker/stats/[...service].js @@ -14,7 +14,8 @@ export default async function handler(req, res) { } try { - const docker = new Docker(getDockerArguments(containerServer)); + const dockerArgs = getDockerArguments(containerServer) + const docker = new Docker(dockerArgs.conn); const containers = await docker.listContainers({ all: true, }); @@ -41,27 +42,30 @@ export default async function handler(req, res) { return; } - // Try with a service deployed in Docker Swarm - const tasks = await docker.listTasks({ - filters: { - service: [containerName], - // A service can have several offline containers, so we only look for an active one. - 'desired-state': ['running'] - } - }).catch(() => []); + // Try with a service deployed in Docker Swarm, if enabled + if (dockerArgs.swarm) { + const tasks = await docker.listTasks({ + filters: { + service: [containerName], + // A service can have several offline containers, so we only look for an active one. + "desired-state": ["running"], + }, + }) + .catch(() => []); - // For now we are only interested in the first one (in case replicas > 1). - // TODO: Show the result for all replicas/containers? - const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID + // For now we are only interested in the first one (in case replicas > 1). + // TODO: Show the result for all replicas/containers? + const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID; - if (taskContainerId) { - const container = docker.getContainer(taskContainerId); - const stats = await container.stats({ stream: false }); + if (taskContainerId) { + const container = docker.getContainer(taskContainerId); + const stats = await container.stats({ stream: false }); - res.status(200).json({ - stats, - }); - return; + res.status(200).json({ + stats, + }); + return; + } } res.status(200).send({ diff --git a/src/pages/api/docker/status/[...service].js b/src/pages/api/docker/status/[...service].js index 71635d1e6..fa54e6f3b 100644 --- a/src/pages/api/docker/status/[...service].js +++ b/src/pages/api/docker/status/[...service].js @@ -13,7 +13,8 @@ export default async function handler(req, res) { } try { - const docker = new Docker(getDockerArguments(containerServer)); + const dockerArgs = getDockerArguments(containerServer); + const docker = new Docker(dockerArgs.conn); const containers = await docker.listContainers({ all: true, }); @@ -35,30 +36,33 @@ export default async function handler(req, res) { return res.status(200).json({ status: info.State.Status, - health: info.State.Health?.Status + health: info.State.Health?.Status, }); } - const tasks = await docker.listTasks({ - filters: { - service: [containerName], - // A service can have several offline containers, we only look for an active one. - 'desired-state': ['running'] - } - }).catch(() => []); + if (dockerArgs.swarm) { + const tasks = await docker.listTasks({ + filters: { + service: [containerName], + // A service can have several offline containers, we only look for an active one. + "desired-state": ["running"], + }, + }) + .catch(() => []); - // For now we are only interested in the first one (in case replicas > 1). - // TODO: Show the result for all replicas/containers? - const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID + // For now we are only interested in the first one (in case replicas > 1). + // TODO: Show the result for all replicas/containers? + const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID; - if (taskContainerId) { - const container = docker.getContainer(taskContainerId); - const info = await container.inspect(); + if (taskContainerId) { + const container = docker.getContainer(taskContainerId); + const info = await container.inspect(); - return res.status(200).json({ - status: info.State.Status, - health: info.State.Health?.Status - }); + return res.status(200).json({ + status: info.State.Status, + health: info.State.Health?.Status, + }); + } } return res.status(200).send({ diff --git a/src/utils/config/docker.js b/src/utils/config/docker.js index 9aef74086..ada0c031e 100644 --- a/src/utils/config/docker.js +++ b/src/utils/config/docker.js @@ -22,11 +22,11 @@ export default function getDockerArguments(server) { if (servers[server]) { if (servers[server].socket) { - return { socketPath: servers[server].socket }; + return { conn: { socketPath: servers[server].socket }, swarm: servers[server].swarm }; } if (servers[server].host) { - return { host: servers[server].host, port: servers[server].port || null }; + return { conn: { host: servers[server].host, port: servers[server].port || null }, swarm: servers[server].swarm }; } return servers[server]; diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index e0a9f23f1..46bda80fb 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -44,7 +44,7 @@ export async function servicesFromDocker() { const serviceServers = await Promise.all( Object.keys(servers).map(async (serverName) => { - const docker = new Docker(getDockerArguments(serverName)); + const docker = new Docker(getDockerArguments(serverName).conn); const containers = await docker.listContainers({ all: true, }); @@ -167,4 +167,4 @@ export default async function getServiceWidget(group, service) { } return false; -} \ No newline at end of file +} From b7722ed33339cd3e7ada200965aefe849a127b40 Mon Sep 17 00:00:00 2001 From: Vinay Dawani Date: Sun, 11 Dec 2022 03:15:59 -0500 Subject: [PATCH 3/5] check swarm value before passing --- src/utils/config/docker.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/utils/config/docker.js b/src/utils/config/docker.js index ada0c031e..ee8559e03 100644 --- a/src/utils/config/docker.js +++ b/src/utils/config/docker.js @@ -22,11 +22,14 @@ export default function getDockerArguments(server) { if (servers[server]) { if (servers[server].socket) { - return { conn: { socketPath: servers[server].socket }, swarm: servers[server].swarm }; + return { conn: { socketPath: servers[server].socket }, swarm: servers[server].swarm == true ? true : false }; } if (servers[server].host) { - return { conn: { host: servers[server].host, port: servers[server].port || null }, swarm: servers[server].swarm }; + return { + conn: { host: servers[server].host, port: servers[server].port || null }, + swarm: servers[server].swarm == true ? true : false, + }; } return servers[server]; From c720df0805c0b307b924788d5b93752ccc2a6af7 Mon Sep 17 00:00:00 2001 From: Vinay Dawani Date: Sun, 11 Dec 2022 04:01:06 -0500 Subject: [PATCH 4/5] double negation instead of ternary. force boolean --- src/utils/config/docker.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/config/docker.js b/src/utils/config/docker.js index ee8559e03..7e1422e0f 100644 --- a/src/utils/config/docker.js +++ b/src/utils/config/docker.js @@ -22,13 +22,13 @@ export default function getDockerArguments(server) { if (servers[server]) { if (servers[server].socket) { - return { conn: { socketPath: servers[server].socket }, swarm: servers[server].swarm == true ? true : false }; + return { conn: { socketPath: servers[server].socket }, swarm: !!servers[server].swarm }; } if (servers[server].host) { return { conn: { host: servers[server].host, port: servers[server].port || null }, - swarm: servers[server].swarm == true ? true : false, + swarm: !!servers[server].swarm, }; } From 9188f5cdd90c28ca4cd9b0d7fe2967f0dcb46957 Mon Sep 17 00:00:00 2001 From: Vinay Dawani Date: Sun, 11 Dec 2022 12:49:23 -0500 Subject: [PATCH 5/5] cleanup --- src/pages/api/docker/stats/[...service].js | 2 +- src/utils/config/service-helpers.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/api/docker/stats/[...service].js b/src/pages/api/docker/stats/[...service].js index 0258bc68d..82604f8c7 100644 --- a/src/pages/api/docker/stats/[...service].js +++ b/src/pages/api/docker/stats/[...service].js @@ -14,7 +14,7 @@ export default async function handler(req, res) { } try { - const dockerArgs = getDockerArguments(containerServer) + const dockerArgs = getDockerArguments(containerServer); const docker = new Docker(dockerArgs.conn); const containers = await docker.listContainers({ all: true, diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index 46bda80fb..623b7d6be 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -167,4 +167,4 @@ export default async function getServiceWidget(group, service) { } return false; -} +} \ No newline at end of file