From e6801b5dc28863242341ff02770f86d1005956cf Mon Sep 17 00:00:00 2001 From: navyadas-dev Date: Tue, 12 May 2026 13:00:10 +0530 Subject: [PATCH 1/2] NMD-872-nomad [GH Issue #26155]: System jobs on node pools scaled to 0 show up in UI as failed --- ui/app/components/job-status/panel/steady.js | 13 +++++---- ui/app/models/job.js | 28 +++++++++++++++----- ui/tests/acceptance/jobs-list-test.js | 2 +- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/ui/app/components/job-status/panel/steady.js b/ui/app/components/job-status/panel/steady.js index d3383dec6ea..47987750434 100644 --- a/ui/app/components/job-status/panel/steady.js +++ b/ui/app/components/job-status/panel/steady.js @@ -270,15 +270,18 @@ export default class JobStatusPanelSteadyComponent extends Component { // If any allocations are failed, lost, or unplaced in a steady state, the job is "Degraded" const failedOrLostAllocs = [ - ...this.allocBlocks.failed?.healthy?.nonCanary, - ...this.allocBlocks.lost?.healthy?.nonCanary, - ...this.allocBlocks.unplaced?.healthy?.nonCanary, + ...(this.allocBlocks.failed?.healthy?.nonCanary || []), + ...(this.allocBlocks.lost?.healthy?.nonCanary || []), + ...(this.allocBlocks.unplaced?.healthy?.nonCanary || []), ]; - if (failedOrLostAllocs.length === totalAllocs) { + if (totalAllocs > 0 && failedOrLostAllocs.length >= totalAllocs) { return { label: 'Failed', state: 'critical' }; - } else { + } else if (failedOrLostAllocs.length > 0) { return { label: 'Degraded', state: 'warning' }; } + + // If no allocations and no failures, show as scaled down + return { label: 'Scaled Down', state: 'neutral' }; } } diff --git a/ui/app/models/job.js b/ui/app/models/job.js index 065a3014e1f..be02bab33ba 100644 --- a/ui/app/models/job.js +++ b/ui/app/models/job.js @@ -251,11 +251,22 @@ export default class Job extends Model { // If the job is scaled down to 0 desired allocations, we shouldn't call it "failed"; // we should indicate that it is deliberately set to not have any running parts. // System/Sysbatch jobs (hasClientStatus) get their totalAllocs from expectedRunningAllocCount, - // which is a best-guess-based-on-whats-running number. This means that if there are no current allocs, - // because they've been GC'd, we don't know if they were deliberately scaled down or failed. - // Safer in this case to show as failed rather than imply a deliberate scale-down. - if (totalAllocs === 0 && !this.hasClientStatus) { - return { label: 'Scaled Down', state: 'neutral' }; + // which is a best-guess-based-on-whats-running number. For these jobs, if there are no + // current allocs AND no failed/lost/unplaced allocs to inspect, we treat the job as + // "Scaled Down" rather than "Failed" — the most common cause is that all eligible nodes + // (e.g. a node pool) have been intentionally scaled to zero. See GH-26155. + if (totalAllocs === 0) { + if (!this.hasClientStatus) { + return { label: 'Scaled Down', state: 'neutral' }; + } + const hasFailureSignal = + (this.allocBlocks.failed?.healthy?.nonCanary?.length || 0) + + (this.allocBlocks.lost?.healthy?.nonCanary?.length || 0) + + (this.allocBlocks.unplaced?.healthy?.nonCanary?.length || 0) > + 0; + if (!hasFailureSignal) { + return { label: 'Scaled Down', state: 'neutral' }; + } } // If the job was requested initially, but a subsequent request for it was @@ -304,11 +315,14 @@ export default class Job extends Model { ...this.allocBlocks.unplaced?.healthy?.nonCanary, ]; - if (failedOrLostAllocs.length >= totalAllocs) { + if (totalAllocs > 0 && failedOrLostAllocs.length >= totalAllocs) { return { label: 'Failed', state: 'critical' }; - } else { + } else if (failedOrLostAllocs.length > 0) { return { label: 'Degraded', state: 'warning' }; } + + // If no allocations and no failures, show as scaled down + return { label: 'Scaled Down', state: 'neutral' }; } @fragment('structured-attributes') meta; diff --git a/ui/tests/acceptance/jobs-list-test.js b/ui/tests/acceptance/jobs-list-test.js index 46b3bb66c64..628be465d58 100644 --- a/ui/tests/acceptance/jobs-list-test.js +++ b/ui/tests/acceptance/jobs-list-test.js @@ -764,7 +764,7 @@ module('Acceptance | jobs list', function (hooks) { .hasText('Scaled Down', 'Scaled down job is scaled down'); assert .dom('[data-test-job-row="ancient-system-job"] [data-test-job-status]') - .hasText('Failed', 'System job with no allocs is failed'); + .hasText('Scaled Down', 'System job with no allocs is scaled down'); await percySnapshot(assert); }); From 96350aeff8a084d1ca2be7c7b8c79819eb646471 Mon Sep 17 00:00:00 2001 From: navyadas-dev Date: Tue, 12 May 2026 13:59:55 +0530 Subject: [PATCH 2/2] NMD-872-Removed the unused eslint-disable directive --- ui/app/components/job-status/panel/steady.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/app/components/job-status/panel/steady.js b/ui/app/components/job-status/panel/steady.js index 47987750434..81239deb23a 100644 --- a/ui/app/components/job-status/panel/steady.js +++ b/ui/app/components/job-status/panel/steady.js @@ -1,4 +1,3 @@ -/* eslint-disable no-unsafe-optional-chaining */ /** * Copyright IBM Corp. 2015, 2025 * SPDX-License-Identifier: BUSL-1.1