Ver Fonte

web: stop works off the recipes actually running on the cluster — single running recipe stops directly (no picking), several get a picker of running ones only, container list names the node; serve-form fallback kept for up-but-empty clusters

Alexander Korolev há 2 semanas atrás
pai
commit
5eecadc573
1 ficheiros alterados com 30 adições e 4 exclusões
  1. 30 4
      src/web/ui.html

+ 30 - 4
src/web/ui.html

@@ -1812,9 +1812,35 @@ function doServe(cluster) {
 function doStop(cluster) {
   const snap = cur();
   const c = snap ? snap.clusters.find((x) => x.name === cluster) : null;
-  const containers = c ? c.nodes.flatMap((n) => n.containers) : [];
-  const recipe = recipeOf(cluster);
-  if (!recipe) { alert("pick the recipe to stop first"); return; }
+  const containers = (c ? c.nodes : []).flatMap((n) => n.containers.map((x) => ({ ...x, node: n.name })));
+  // stop what is actually running here — never the whole recipe catalogue
+  const running = [...new Set(containers.map((x) => x.recipe).filter(Boolean))];
+  if (!running.length) {
+    // up but nothing detected: fall back to the serve-form pick (a stale
+    // serve the probe missed is still worth stopping)
+    const recipe = recipeOf(cluster);
+    if (!recipe) { alert(`nothing is running on ${cluster}`); return; }
+    stopDialog(cluster, recipe, containers);
+    return;
+  }
+  if (running.length === 1) { stopDialog(cluster, running[0], containers); return; }
+  const body = document.createElement("div");
+  body.className = "body";
+  body.innerHTML = `Several recipes are running on <code>${esc(cluster)}</code> — pick the one to stop:`;
+  const sel = document.createElement("select");
+  sel.style.cssText = "width:100%;margin:8px 0;padding:6px;background:var(--btn);color:var(--fg);border:1px solid var(--border);border-radius:6px;";
+  for (const r of running) {
+    const o = document.createElement("option");
+    o.value = r; o.textContent = r;
+    sel.appendChild(o);
+  }
+  body.appendChild(sel);
+  openDialogHtml(`stop ${cluster}`, body, () => stopDialog(cluster, sel.value, containers));
+}
+
+function stopDialog(cluster, recipe, containers) {
+  const snap = cur();
+  const c = snap ? snap.clusters.find((x) => x.name === cluster) : null;
   const body = document.createElement("div");
   body.className = "body";
   const nodeSel = document.createElement("select");
@@ -1822,7 +1848,7 @@ function doStop(cluster) {
   nodeSel.title = "stop on one node instead of all";
   nodeSel.innerHTML = `<option value=''>all nodes</option>` + (c ? c.nodes.map((n) => `<option value='${esc(n.name)}'>${esc(n.name)}</option>`).join("") : "");
   const list = containers.length
-    ? `<ul class="cbox">${containers.map((x) => `<li><b>${esc(x.name)}</b> — ${esc(x.status)}</li>`).join("")}</ul>`
+    ? `<ul class="cbox">${containers.map((x) => `<li><b>${esc(x.name)}</b> — ${esc(x.status)} <span class="dim">on ${esc(x.node)}</span></li>`).join("")}</ul>`
     : `<div class="cbox">no containers detected on ${esc(cluster)} (recipe may not be running here)</div>`;
   body.innerHTML = `Will run <code>sm121 stop</code> for <code>${esc(recipe)}</code> on <code>${esc(cluster)}</code>. Node: <span data-stopnode></span>. Currently running:${list}`;
   body.querySelector("[data-stopnode]").replaceWith(nodeSel);