From f74275293a0be41c566bbeac1a100f66b6e5cccd Mon Sep 17 00:00:00 2001
From: shamoon <4887959+shamoon@users.noreply.github.com>
Date: Mon, 13 Feb 2023 00:00:39 -0800
Subject: [PATCH] Prefer swarm task containers locally for status / stats

---
 src/pages/api/docker/stats/[...service].js  | 24 +++++++++++------
 src/pages/api/docker/status/[...service].js | 30 ++++++++++++++-------
 2 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/src/pages/api/docker/stats/[...service].js b/src/pages/api/docker/stats/[...service].js
index 84e90065..0ca30f00 100644
--- a/src/pages/api/docker/stats/[...service].js
+++ b/src/pages/api/docker/stats/[...service].js
@@ -53,17 +53,25 @@ export default async function handler(req, res) {
         })
         .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;
-
+      // We can only get stats for 'local' containers so try to find one
+      const localContainerIDs = containers.map(c => c.Id);
+      const task = tasks.find(t => localContainerIDs.includes(t.Status?.ContainerStatus?.ContainerID)) ?? tasks.at(0);
+      const taskContainerId = task?.Status?.ContainerStatus?.ContainerID;
+      
       if (taskContainerId) {
-        const container = docker.getContainer(taskContainerId);
-        const stats = await container.stats({ stream: false });
+        try {
+          const container = docker.getContainer(taskContainerId);
+          const stats = await container.stats({ stream: false });
 
-        return res.status(200).json({
-          stats,
-        });
+          return res.status(200).json({
+            stats,
+          });
+        } catch (e) {
+          return res.status(200).json({
+            error: "Unable to retrieve stats"
+          })
+        }
       }
     }
 
diff --git a/src/pages/api/docker/status/[...service].js b/src/pages/api/docker/status/[...service].js
index f232eb98..4a706c4d 100644
--- a/src/pages/api/docker/status/[...service].js
+++ b/src/pages/api/docker/status/[...service].js
@@ -53,18 +53,28 @@ export default async function handler(req, res) {
         })
         .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;
-
+      // We can only get stats for 'local' containers so try to find one
+      const localContainerIDs = containers.map(c => c.Id);
+      const task = tasks.find(t => localContainerIDs.includes(t.Status?.ContainerStatus?.ContainerID)) ?? tasks.at(0);
+      const taskContainerId = task?.Status?.ContainerStatus?.ContainerID;
+      
       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,
-        });
+        try {
+          const container = docker.getContainer(taskContainerId);
+          const info = await container.inspect();
+  
+          return res.status(200).json({
+            status: info.State.Status,
+            health: info.State.Health?.Status,
+          });
+        } catch (e) {
+          if (task) {
+            return res.status(200).json({
+              status: task.Status.State
+            })
+          }
+        }
       }
     }