mirror of
https://github.com/kemko/nomad.git
synced 2026-01-05 01:45:44 +03:00
[ui] Disconnected Clients: "Unknown" allocations in the UI (#12544)
* Unknown status for allocations accounted for * Canary string removed * Test cleanup * Generate unknown in mirage * aacidentally oovervoowled * Update ui/app/components/allocation-status-bar.js Co-authored-by: Derek Strickland <1111455+DerekStrickland@users.noreply.github.com> * Disconnected state on job status in client * Renaming Disconnected to Unknown in the job-status-in-client * Unknown accounted for on job rows filtering and testsfix * Adding lostAllocs as a computed dependency * Unknown client status within acceptance test * Swatches updated and PR comments addressed * Unknown and disconnected added to test fixtures Co-authored-by: Derek Strickland <1111455+DerekStrickland@users.noreply.github.com>
This commit is contained in:
@@ -25,7 +25,7 @@ export default class AllocationStatusBar extends DistributionBar {
|
||||
}
|
||||
|
||||
@computed(
|
||||
'allocationContainer.{queuedAllocs,completeAllocs,failedAllocs,runningAllocs,startingAllocs}',
|
||||
'allocationContainer.{queuedAllocs,completeAllocs,failedAllocs,runningAllocs,startingAllocs,lostAllocs,unknownAllocs}',
|
||||
'job.namespace'
|
||||
)
|
||||
get data() {
|
||||
@@ -39,7 +39,8 @@ export default class AllocationStatusBar extends DistributionBar {
|
||||
'failedAllocs',
|
||||
'runningAllocs',
|
||||
'startingAllocs',
|
||||
'lostAllocs'
|
||||
'lostAllocs',
|
||||
'unknownAllocs'
|
||||
);
|
||||
return [
|
||||
{
|
||||
@@ -67,6 +68,13 @@ export default class AllocationStatusBar extends DistributionBar {
|
||||
className: 'complete',
|
||||
legendLink: this.generateLegendLink(this.job, 'complete'),
|
||||
},
|
||||
{
|
||||
label: 'Unknown',
|
||||
value: allocs.unknownAllocs,
|
||||
className: 'unknown',
|
||||
legendLink: this.generateLegendLink(this.job, 'unknown'),
|
||||
help: 'Allocation is unknown since its node is disconnected.',
|
||||
},
|
||||
{
|
||||
label: 'Failed',
|
||||
value: allocs.failedAllocs,
|
||||
|
||||
@@ -23,6 +23,7 @@ export default class JobClientStatusBar extends DistributionBar {
|
||||
failed,
|
||||
lost,
|
||||
notScheduled,
|
||||
unknown,
|
||||
} = this.jobClientStatus.byStatus;
|
||||
|
||||
return [
|
||||
@@ -71,6 +72,18 @@ export default class JobClientStatusBar extends DistributionBar {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Unknown',
|
||||
value: unknown.length,
|
||||
className: 'unknown',
|
||||
legendLink: {
|
||||
queryParams: {
|
||||
status: JSON.stringify(['unknown']),
|
||||
namespace: this.job.namespace.get('id'),
|
||||
},
|
||||
},
|
||||
help: 'Some allocations for this job were degraded or lost connectivity.',
|
||||
},
|
||||
{
|
||||
label: 'Degraded',
|
||||
value: degraded.length,
|
||||
|
||||
@@ -48,6 +48,7 @@ export default class ClientRow extends Component {
|
||||
runningAllocs: 0,
|
||||
startingAllocs: 0,
|
||||
lostAllocs: 0,
|
||||
unknownAllocs: 0,
|
||||
};
|
||||
|
||||
switch (this.args.row.model.jobStatus) {
|
||||
@@ -77,6 +78,9 @@ export default class ClientRow extends Component {
|
||||
case 'starting':
|
||||
statusSummary.startingAllocs++;
|
||||
break;
|
||||
case 'unknown':
|
||||
statusSummary.unknownAllocs++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +211,7 @@ export default class ClientController extends Controller.extend(
|
||||
{ key: 'complete', label: 'Complete' },
|
||||
{ key: 'failed', label: 'Failed' },
|
||||
{ key: 'lost', label: 'Lost' },
|
||||
{ key: 'unknown', label: 'Unknown' },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ export default class IndexController extends Controller.extend(
|
||||
{ key: 'down', label: 'Down' },
|
||||
{ key: 'ineligible', label: 'Ineligible' },
|
||||
{ key: 'draining', label: 'Draining' },
|
||||
{ key: 'disconnected', label: 'Disconnected' },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ export default class AllocationsController extends Controller.extend(
|
||||
{ key: 'complete', label: 'Complete' },
|
||||
{ key: 'failed', label: 'Failed' },
|
||||
{ key: 'lost', label: 'Lost' },
|
||||
{ key: 'unknown', label: 'Unknown' },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ export default class ClientsController extends Controller.extend(
|
||||
{ key: 'degraded', label: 'Degraded' },
|
||||
{ key: 'failed', label: 'Failed' },
|
||||
{ key: 'lost', label: 'Lost' },
|
||||
{ key: 'unknown', label: 'Unknown' },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ export default class TaskGroupController extends Controller.extend(
|
||||
{ key: 'complete', label: 'Complete' },
|
||||
{ key: 'failed', label: 'Failed' },
|
||||
{ key: 'lost', label: 'Lost' },
|
||||
{ key: 'unknown', label: 'Unknown' },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,9 @@ const STATUS_ORDER = {
|
||||
pending: 1,
|
||||
running: 2,
|
||||
complete: 3,
|
||||
failed: 4,
|
||||
lost: 5,
|
||||
unknown: 4,
|
||||
failed: 5,
|
||||
lost: 6,
|
||||
};
|
||||
|
||||
@classic
|
||||
@@ -83,6 +84,7 @@ export default class Allocation extends Model {
|
||||
complete: 'is-complete',
|
||||
failed: 'is-error',
|
||||
lost: 'is-light',
|
||||
unknown: 'is-unknown',
|
||||
};
|
||||
|
||||
return classMap[this.clientStatus] || 'is-dark';
|
||||
|
||||
@@ -17,6 +17,7 @@ export default class JobSummary extends Model {
|
||||
@sumAggregation('taskGroupSummaries', 'runningAllocs') runningAllocs;
|
||||
@sumAggregation('taskGroupSummaries', 'completeAllocs') completeAllocs;
|
||||
@sumAggregation('taskGroupSummaries', 'failedAllocs') failedAllocs;
|
||||
@sumAggregation('taskGroupSummaries', 'unknownAllocs') unknownAllocs;
|
||||
@sumAggregation('taskGroupSummaries', 'lostAllocs') lostAllocs;
|
||||
|
||||
@collect(
|
||||
@@ -25,7 +26,8 @@ export default class JobSummary extends Model {
|
||||
'runningAllocs',
|
||||
'completeAllocs',
|
||||
'failedAllocs',
|
||||
'lostAllocs'
|
||||
'lostAllocs',
|
||||
'unknownAllocs'
|
||||
)
|
||||
allocsList;
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ export default class Job extends Model {
|
||||
@alias('summary.completeAllocs') completeAllocs;
|
||||
@alias('summary.failedAllocs') failedAllocs;
|
||||
@alias('summary.lostAllocs') lostAllocs;
|
||||
@alias('summary.unknownAllocs') unknownAllocs;
|
||||
@alias('summary.totalAllocs') totalAllocs;
|
||||
@alias('summary.pendingChildren') pendingChildren;
|
||||
@alias('summary.runningChildren') runningChildren;
|
||||
|
||||
@@ -13,6 +13,7 @@ export default class TaskGroupSummary extends Fragment {
|
||||
@attr('number') completeAllocs;
|
||||
@attr('number') failedAllocs;
|
||||
@attr('number') lostAllocs;
|
||||
@attr('number') unknownAllocs;
|
||||
|
||||
@collect(
|
||||
'queuedAllocs',
|
||||
@@ -20,7 +21,8 @@ export default class TaskGroupSummary extends Fragment {
|
||||
'runningAllocs',
|
||||
'completeAllocs',
|
||||
'failedAllocs',
|
||||
'lostAllocs'
|
||||
'lostAllocs',
|
||||
'unknownAllocs'
|
||||
)
|
||||
allocsList;
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@ $canceled: $dark;
|
||||
.degraded {
|
||||
fill: $degraded;
|
||||
}
|
||||
|
||||
.unknown {
|
||||
fill: $unknown;
|
||||
}
|
||||
}
|
||||
|
||||
.color-swatch {
|
||||
@@ -114,6 +118,10 @@ $canceled: $dark;
|
||||
background: $lost;
|
||||
}
|
||||
|
||||
&.unknown {
|
||||
background: $unknown;
|
||||
}
|
||||
|
||||
&.not-scheduled {
|
||||
background: $not-scheduled;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
$color-sequence: $orange, $yellow, $green, $turquoise, $blue, $purple, $red;
|
||||
$color-sequence: $orange, $yellow, $green, $turquoise, $blue, $purple,
|
||||
$red;
|
||||
|
||||
@for $i from 1 through length($color-sequence) {
|
||||
.slice-#{$i - 1} {
|
||||
@@ -113,6 +114,12 @@
|
||||
color: darken($grey-blue, 20%);
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent Orphaned last-elements in the list
|
||||
// from being visually centered
|
||||
&:nth-child(2n + 1):last-child {
|
||||
margin-right: calc(35% + 0.75em);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
color: $nomad-green-dark;
|
||||
}
|
||||
|
||||
&.node-disconnected {
|
||||
color: $yellow;
|
||||
}
|
||||
|
||||
&.node-down {
|
||||
color: $danger;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@
|
||||
color: $orange-invert;
|
||||
}
|
||||
|
||||
&.is-unknown {
|
||||
background: $unknown;
|
||||
color: $primary-invert;
|
||||
}
|
||||
|
||||
&.is-hollow {
|
||||
font-weight: $weight-semibold;
|
||||
color: darken($grey-blue, 20%);
|
||||
|
||||
@@ -5,12 +5,14 @@ $purple: $terraform-purple;
|
||||
$red: #c84034;
|
||||
$grey-blue: #bbc4d1;
|
||||
$blue-light: #c0d5ff;
|
||||
$yellow: #fac402;
|
||||
|
||||
$primary: $nomad-green;
|
||||
$warning: $orange;
|
||||
$warning-invert: $white;
|
||||
$danger: $red;
|
||||
$info: $blue;
|
||||
$unknown: $yellow;
|
||||
$dark: #234;
|
||||
$dark-2: darken($dark, 5%);
|
||||
$dark-3: darken($dark, 10%);
|
||||
@@ -25,8 +27,8 @@ $size-7: 0.85rem;
|
||||
|
||||
$title-weight: $weight-semibold;
|
||||
|
||||
$family-sans-serif: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu,
|
||||
Cantarell, 'Helvetica Neue', sans-serif;
|
||||
$family-sans-serif: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;
|
||||
|
||||
$text: $black;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ const STATUS = [
|
||||
'degraded',
|
||||
'failed',
|
||||
'lost',
|
||||
'unknown',
|
||||
];
|
||||
|
||||
// An Ember.Computed property that computes the aggregated status of a job in a
|
||||
@@ -137,5 +138,9 @@ function jobStatus(allocs, expected) {
|
||||
return 'running';
|
||||
}
|
||||
|
||||
if (summary['unknown'] > 0) {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
return 'starting';
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export default Factory.extend({
|
||||
namespace: null,
|
||||
|
||||
withSummary: trait({
|
||||
Summary: function() {
|
||||
Summary: function () {
|
||||
return this.groupNames.reduce((summary, group) => {
|
||||
summary[group] = {
|
||||
Queued: faker.random.number(10),
|
||||
@@ -18,6 +18,7 @@ export default Factory.extend({
|
||||
Running: faker.random.number(10),
|
||||
Starting: faker.random.number(10),
|
||||
Lost: faker.random.number(10),
|
||||
Unknown: faker.random.number(10),
|
||||
};
|
||||
return summary;
|
||||
}, {});
|
||||
|
||||
@@ -1140,12 +1140,21 @@ module('Acceptance | client detail', function (hooks) {
|
||||
testFacet('Status', {
|
||||
facet: ClientDetail.facets.status,
|
||||
paramName: 'status',
|
||||
expectedOptions: ['Pending', 'Running', 'Complete', 'Failed', 'Lost'],
|
||||
expectedOptions: [
|
||||
'Pending',
|
||||
'Running',
|
||||
'Complete',
|
||||
'Failed',
|
||||
'Lost',
|
||||
'Unknown',
|
||||
],
|
||||
async beforeEach() {
|
||||
server.createList('job', 5, { createAllocations: false });
|
||||
['pending', 'running', 'complete', 'failed', 'lost'].forEach((s) => {
|
||||
server.createList('allocation', 5, { clientStatus: s });
|
||||
});
|
||||
['pending', 'running', 'complete', 'failed', 'lost', 'unknown'].forEach(
|
||||
(s) => {
|
||||
server.createList('allocation', 5, { clientStatus: s });
|
||||
}
|
||||
);
|
||||
|
||||
await ClientDetail.visit({ id: node.id });
|
||||
},
|
||||
|
||||
@@ -276,6 +276,7 @@ module('Acceptance | clients list', function (hooks) {
|
||||
'Down',
|
||||
'Ineligible',
|
||||
'Draining',
|
||||
'Disconnected',
|
||||
],
|
||||
async beforeEach() {
|
||||
server.create('agent');
|
||||
|
||||
@@ -152,11 +152,20 @@ module('Acceptance | job allocations', function (hooks) {
|
||||
testFacet('Status', {
|
||||
facet: Allocations.facets.status,
|
||||
paramName: 'status',
|
||||
expectedOptions: ['Pending', 'Running', 'Complete', 'Failed', 'Lost'],
|
||||
expectedOptions: [
|
||||
'Pending',
|
||||
'Running',
|
||||
'Complete',
|
||||
'Failed',
|
||||
'Lost',
|
||||
'Unknown',
|
||||
],
|
||||
async beforeEach() {
|
||||
['pending', 'running', 'complete', 'failed', 'lost'].forEach((s) => {
|
||||
server.createList('allocation', 5, { clientStatus: s });
|
||||
});
|
||||
['pending', 'running', 'complete', 'failed', 'lost', 'unknown'].forEach(
|
||||
(s) => {
|
||||
server.createList('allocation', 5, { clientStatus: s });
|
||||
}
|
||||
);
|
||||
await Allocations.visit({ id: job.id });
|
||||
},
|
||||
filter: (alloc, selection) =>
|
||||
|
||||
@@ -200,6 +200,7 @@ module('Acceptance | job clients', function (hooks) {
|
||||
'Degraded',
|
||||
'Failed',
|
||||
'Lost',
|
||||
'Unknown',
|
||||
],
|
||||
async beforeEach() {
|
||||
await Clients.visit({ id: job.id });
|
||||
|
||||
@@ -669,11 +669,20 @@ module('Acceptance | task group detail', function (hooks) {
|
||||
testFacet('Status', {
|
||||
facet: TaskGroup.facets.status,
|
||||
paramName: 'status',
|
||||
expectedOptions: ['Pending', 'Running', 'Complete', 'Failed', 'Lost'],
|
||||
expectedOptions: [
|
||||
'Pending',
|
||||
'Running',
|
||||
'Complete',
|
||||
'Failed',
|
||||
'Lost',
|
||||
'Unknown',
|
||||
],
|
||||
async beforeEach() {
|
||||
['pending', 'running', 'complete', 'failed', 'lost'].forEach((s) => {
|
||||
server.createList('allocation', 5, { clientStatus: s });
|
||||
});
|
||||
['pending', 'running', 'complete', 'failed', 'lost', 'unknown'].forEach(
|
||||
(s) => {
|
||||
server.createList('allocation', 5, { clientStatus: s });
|
||||
}
|
||||
);
|
||||
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
|
||||
},
|
||||
filter: (alloc, selection) =>
|
||||
|
||||
@@ -29,6 +29,7 @@ module('Integration | Component | job-client-status-bar', function (hooks) {
|
||||
failed: [],
|
||||
lost: [],
|
||||
notScheduled: [],
|
||||
unknown: [],
|
||||
},
|
||||
},
|
||||
isNarrow: true,
|
||||
|
||||
@@ -19,6 +19,7 @@ module('Unit | Model | job', function (hooks) {
|
||||
completeAllocs: 4,
|
||||
failedAllocs: 5,
|
||||
lostAllocs: 6,
|
||||
unknownAllocs: 7,
|
||||
},
|
||||
{
|
||||
name: 'two',
|
||||
@@ -28,6 +29,7 @@ module('Unit | Model | job', function (hooks) {
|
||||
completeAllocs: 8,
|
||||
failedAllocs: 10,
|
||||
lostAllocs: 12,
|
||||
unknownAllocs: 14,
|
||||
},
|
||||
{
|
||||
name: 'three',
|
||||
@@ -37,6 +39,7 @@ module('Unit | Model | job', function (hooks) {
|
||||
completeAllocs: 12,
|
||||
failedAllocs: 15,
|
||||
lostAllocs: 18,
|
||||
unknownAllocs: 21,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -74,6 +74,7 @@ module('Unit | Util | JobClientStatus', function () {
|
||||
notScheduled: [],
|
||||
queued: [],
|
||||
starting: [],
|
||||
unknown: [],
|
||||
},
|
||||
totalNodes: 1,
|
||||
};
|
||||
@@ -110,6 +111,7 @@ module('Unit | Util | JobClientStatus', function () {
|
||||
notScheduled: [],
|
||||
queued: [],
|
||||
starting: [],
|
||||
unknown: [],
|
||||
},
|
||||
totalNodes: 1,
|
||||
};
|
||||
@@ -146,6 +148,7 @@ module('Unit | Util | JobClientStatus', function () {
|
||||
notScheduled: [],
|
||||
queued: [],
|
||||
starting: [],
|
||||
unknown: [],
|
||||
},
|
||||
totalNodes: 1,
|
||||
};
|
||||
@@ -182,6 +185,7 @@ module('Unit | Util | JobClientStatus', function () {
|
||||
notScheduled: [],
|
||||
queued: [],
|
||||
starting: [],
|
||||
unknown: [],
|
||||
},
|
||||
totalNodes: 1,
|
||||
};
|
||||
@@ -218,6 +222,7 @@ module('Unit | Util | JobClientStatus', function () {
|
||||
notScheduled: [],
|
||||
queued: [],
|
||||
starting: [],
|
||||
unknown: [],
|
||||
},
|
||||
totalNodes: 1,
|
||||
};
|
||||
@@ -250,6 +255,7 @@ module('Unit | Util | JobClientStatus', function () {
|
||||
notScheduled: ['node-1'],
|
||||
queued: [],
|
||||
starting: [],
|
||||
unknown: [],
|
||||
},
|
||||
totalNodes: 1,
|
||||
};
|
||||
@@ -286,6 +292,7 @@ module('Unit | Util | JobClientStatus', function () {
|
||||
notScheduled: [],
|
||||
queued: ['node-1'],
|
||||
starting: [],
|
||||
unknown: [],
|
||||
},
|
||||
totalNodes: 1,
|
||||
};
|
||||
@@ -323,6 +330,7 @@ module('Unit | Util | JobClientStatus', function () {
|
||||
notScheduled: [],
|
||||
queued: [],
|
||||
starting: [],
|
||||
unknown: [],
|
||||
},
|
||||
totalNodes: 1,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user