Improve docker swarm status check

This commit is contained in:
Raphaël Catarino 2023-02-14 13:54:52 +01:00
parent 8a6343dee7
commit 08f9120326
2 changed files with 50 additions and 24 deletions

View File

@ -7,15 +7,21 @@ export default function Status({ service }) {
const { data, error } = useSWR(`/api/docker/status/${service.container}/${service.server || ""}`); const { data, error } = useSWR(`/api/docker/status/${service.container}/${service.server || ""}`);
if (error) { if (error) {
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.status}> <div
className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden"
title={data.status}
>
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div> <div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
</div> </div>;
} }
if (data && data.status === "running") { if (data && data.status === "running") {
if (data.health === "starting") { if (data.health === "starting") {
return ( return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.health}> <div
className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden"
title={data.health}
>
<div className="text-[8px] font-bold text-blue-500/80 uppercase">{data.health}</div> <div className="text-[8px] font-bold text-blue-500/80 uppercase">{data.health}</div>
</div> </div>
); );
@ -23,22 +29,31 @@ export default function Status({ service }) {
if (data.health === "unhealthy") { if (data.health === "unhealthy") {
return ( return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.health}> <div
className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden"
title={data.health}
>
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.health}</div> <div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.health}</div>
</div> </div>
); );
} }
return ( return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.health || data.status}> <div
className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden"
title={data.health || data.status}
>
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health || data.status}</div> <div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health || data.status}</div>
</div> </div>
); );
} }
if (data && (data.status === "not found" || data.status === "exited")) { if (data && (data.status === "not found" || data.status === "exited" || data.status?.startsWith("partial"))) {
return ( return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.status}> <div
className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden"
title={data.status}
>
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.status}</div> <div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.status}</div>
</div> </div>
); );

View File

@ -44,37 +44,48 @@ export default async function handler(req, res) {
} }
if (dockerArgs.swarm) { if (dockerArgs.swarm) {
const tasks = await docker.listTasks({ const serviceInfo = await docker
.getService(containerName)
.inspect()
.catch(() => undefined);
if (!serviceInfo) {
return res.status(404).send({
status: "not found",
});
}
const tasks = await docker
.listTasks({
filters: { filters: {
service: [containerName], service: [containerName],
// A service can have several offline containers, we only look for an active one.
"desired-state": ["running"], "desired-state": ["running"],
}, },
}) })
.catch(() => []); .catch(() => []);
// For now we are only interested in the first one (in case replicas > 1). const replicas = serviceInfo.Spec.Mode?.Global
// TODO: Show the result for all replicas/containers? ? (await docker.listNodes()).length
const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID; : serviceInfo.Spec.Mode?.Replicated?.Replicas;
if (replicas) {
if (taskContainerId) { if (tasks.length === replicas) {
const container = docker.getContainer(taskContainerId);
const info = await container.inspect();
return res.status(200).json({ return res.status(200).json({
status: info.State.Status, status: `running`,
health: info.State.Health?.Status, });
}
if (tasks.length > 0) {
return res.status(200).json({
status: `partial ${tasks.length}/${replicas}`,
}); });
} }
} }
}
return res.status(200).send({ return res.status(404).send({
error: "not found", status: "not found",
}); });
} catch (e) { } catch (e) {
logger.error(e); logger.error(e);
return res.status(500).send({ return res.status(500).send({
error: {message: e?.message ?? "Unknown error"}, error: { message: e?.message ?? "Unknown error" },
}); });
} }
} }