Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ui, deployments] Show a "Latest Deployment Status" cell within the Job Status panel on steady service jobs #17246

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 41 additions & 33 deletions ui/app/components/job-status/failed-or-lost.hbs
Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
<section class="failed-or-lost">
<h4>
{{@title}}
<span
class="tooltip multiline text-center"
role="tooltip"
aria-label={{@description}}
>
<FlightIcon @name="info" />
<h4>Replaced Allocations</h4>
<div class="failed-or-lost-links">
{{#if @supportsRescheduling}}
<span>
<span
class="tooltip multiline text-center"
role="tooltip"
aria-label="Allocations that have been rescheduled, on another node if possible, due to failure or manual restart"
>
<FlightIcon @name="info" />
</span>
<ConditionalLinkTo
@condition={{@rescheduledAllocs.length}}
@route="jobs.job.allocations"
@model={{@job}}
@query={{hash scheduling='["has-been-rescheduled"]' version=(concat '[' @job.latestDeployment.versionNumber ']')}}
@label="View Allocations"
>
{{@rescheduledAllocs.length}} Rescheduled
</ConditionalLinkTo>
</span>
{{/if}}

<span>
<span
class="tooltip multiline text-center"
role="tooltip"
aria-label="Allocations that have been restarted in-place due to a task failure or manual restart"
>
<FlightIcon @name="info" />
</span>
<ConditionalLinkTo
@condition={{@restartedAllocs.length}}
@route="jobs.job.allocations"
@model={{@job}}
@query={{hash scheduling='["has-been-restarted"]' version=(concat '[' @job.latestDeployment.versionNumber ']')}}
@label="View Allocations"
>
{{@restartedAllocs.length}} Restarted
</ConditionalLinkTo>
</span>
</h4>
{{#if (eq @title "Rescheduled")}}
<ConditionalLinkTo
@condition={{this.shouldLinkToAllocations}}
@route="jobs.job.allocations"
@model={{@job}}
@query={{hash scheduling='["has-been-rescheduled"]' version=(concat '[' @job.latestDeployment.versionNumber ']')}}
@label="View Allocations"
@class="failed-or-lost-link"
>
{{@allocs.length}}
</ConditionalLinkTo>
{{/if}}
{{#if (eq @title "Restarted")}}
<ConditionalLinkTo
@condition={{this.shouldLinkToAllocations}}
@route="jobs.job.allocations"
@model={{@job}}
@query={{hash scheduling='["has-been-restarted"]' version=(concat '[' @job.latestDeployment.versionNumber ']')}}
@label="View Allocations"
@class="failed-or-lost-link"
>
{{@allocs.length}}
</ConditionalLinkTo>
{{/if}}
</div>
</section>
7 changes: 0 additions & 7 deletions ui/app/components/job-status/failed-or-lost.js

This file was deleted.

10 changes: 10 additions & 0 deletions ui/app/components/job-status/latest-deployment.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<section class="latest-deployment">
<LinkTo @route="jobs.job.deployments" @model={{@job}}>
<h4>
Latest Deployment
<FlightIcon @name="arrow-right" />
</h4>
</LinkTo>
<Hds::Badge @text={{capitalize this.status}} @size="small" @color={{this.statusColor}} @type="filled" />
<p>{{this.healthyAllocs}}/{{this.desiredTotal}} Healthy</p>
</section>
31 changes: 31 additions & 0 deletions ui/app/components/job-status/latest-deployment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Component from '@glimmer/component';
import { alias } from '@ember/object/computed';

export default class JobStatusLatestDeploymentComponent extends Component {
@alias('args.job.latestDeployment') deployment;
@alias('deployment.status') status;

get healthyAllocs() {
return this.deployment
.get('taskGroupSummaries')
.mapBy('healthyAllocs')
.reduce((sum, count) => sum + count, 0);
}
get desiredTotal() {
return this.deployment
.get('taskGroupSummaries')
.mapBy('desiredTotal')
.reduce((sum, count) => sum + count, 0);
}

get statusColor() {
switch (this.status) {
case 'successful':
return 'success';
case 'failed':
return 'critical';
default:
return 'neutral';
}
}
}
13 changes: 3 additions & 10 deletions ui/app/components/job-status/panel/deploying.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,10 @@
</legend>

<JobStatus::FailedOrLost
@allocs={{this.rescheduledAllocs}}
@rescheduledAllocs={{this.rescheduledAllocs}}
@restartedAllocs={{this.restartedAllocs}}
@job={{@job}}
@title="Rescheduled"
@description="Allocations that have been rescheduled, on another node if possible, due to failure during deployment"
/>

<JobStatus::FailedOrLost
@allocs={{this.restartedAllocs}}
@job={{@job}}
@title="Restarted"
@description="Allocations that have been restarted in-place due to a task failure during deployment"
@supportsRescheduling={{true}}
/>

</div>
Expand Down
20 changes: 8 additions & 12 deletions ui/app/components/job-status/panel/steady.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
</h3>
<JobStatus::AllocationStatusRow @allocBlocks={{this.allocBlocks}} @steady={{true}} />

<div class="legend-and-summary">
<div class="legend-and-summary {{if @job.latestDeployment "has-latest-deployment"}}">
<legend>
{{#each this.allocTypes as |type|}}
<ConditionalLinkTo
Expand All @@ -58,20 +58,12 @@
{{/each}}
</legend>

{{#if this.supportsRescheduling}}
<JobStatus::FailedOrLost
@allocs={{this.rescheduledAllocs}}
@job={{@job}}
@title="Rescheduled"
@description="Allocations that have been rescheduled, on another node if possible, due to failure"
/>
{{/if}}

<JobStatus::FailedOrLost
@allocs={{this.restartedAllocs}}
@rescheduledAllocs={{this.rescheduledAllocs}}
@restartedAllocs={{this.restartedAllocs}}
@job={{@job}}
@title="Restarted"
@description="Allocations that have been restarted in-place due to a task failure"
@supportsRescheduling={{this.supportsRescheduling}}
/>

<section class="versions">
Expand All @@ -92,6 +84,10 @@
</ul>
</section>

{{#if @job.latestDeployment}}
<JobStatus::LatestDeployment @job={{@job}} />
{{/if}}

</div>

<div class="history-and-params">
Expand Down
28 changes: 18 additions & 10 deletions ui/app/styles/components/job-status-panel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,15 @@
// grid-area: legend-and-summary;
// TODO: may revisit this grid-area later, but is currently used in 2 competing ways
display: grid;
gap: 0.5rem;
grid-template-columns: 55% 15% 15% 15%;
gap: 1rem;
grid-template-columns: 3fr 1fr 1fr;
&.has-latest-deployment {
grid-template-columns: 3fr 1fr 1fr 1fr;
}

& > section > h4,
& > legend > h4 {
& > legend > h4,
& > section > a > h4 {
margin-bottom: 0.5rem;
}

Expand All @@ -62,8 +66,6 @@
gap: 0.5rem;
}
.versions {
display: grid;
gap: 0.5rem;
& > ul {
display: grid;
grid-template-columns: repeat(auto-fit, 100px);
Expand All @@ -76,12 +78,18 @@
}
}
}
.latest-deployment {
h4 svg {
position: relative;
top: 3px;
}
}

.failed-or-lost {
.failed-or-lost-link {
display: block;
font-size: 1.5rem;
font-weight: bold;
.failed-or-lost > div {
display: grid;
gap: 3px;
.tooltip {
top: 3px;
}
}
}
Expand Down
45 changes: 24 additions & 21 deletions ui/tests/acceptance/job-status-panel-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -648,29 +648,29 @@ module('Acceptance | job status panel', function (hooks) {
await visit(`/jobs/${job.id}`);
assert.dom('.job-status-panel').exists();
assert
.dom('.failed-or-lost')
.dom('.failed-or-lost-links > span')
.exists({ count: 2 }, 'Restarted and Rescheduled cells are both present');

let rescheduledCell = [...findAll('.failed-or-lost')][0];
let restartedCell = [...findAll('.failed-or-lost')][1];
// await this.pauseTest();
let rescheduledCell = [...findAll('.failed-or-lost-links > span')][0];
let restartedCell = [...findAll('.failed-or-lost-links > span')][1];

// Check that the title in each cell has the right text
assert.dom(rescheduledCell.querySelector('h4')).hasText('Rescheduled');
assert.dom(restartedCell.querySelector('h4')).hasText('Restarted');
assert.dom(rescheduledCell).hasText('0 Rescheduled');
assert.dom(restartedCell).hasText('0 Restarted');

// Check that both values are zero and non-links
assert
.dom(rescheduledCell.querySelector('a'))
.doesNotExist('Rescheduled cell is not a link');
assert
.dom(rescheduledCell.querySelector('.failed-or-lost-link'))
.hasText('0', 'Rescheduled cell has zero value');
.dom(rescheduledCell)
.hasText('0 Rescheduled', 'Rescheduled cell has zero value');
assert
.dom(restartedCell.querySelector('a'))
.doesNotExist('Restarted cell is not a link');
assert
.dom(restartedCell.querySelector('.failed-or-lost-link'))
.hasText('0', 'Restarted cell has zero value');
.dom(restartedCell)
.hasText('0 Restarted', 'Restarted cell has zero value');

// A wild event appears! Change a recent task event to type "Restarting" in a task state:
this.store
Expand All @@ -687,9 +687,9 @@ module('Acceptance | job status panel', function (hooks) {
await settled();

assert
.dom(restartedCell.querySelector('.failed-or-lost-link'))
.dom(restartedCell)
.hasText(
'1',
'1 Restarted',
'Restarted cell updates when a task event with type "Restarting" is added'
);

Expand All @@ -708,9 +708,9 @@ module('Acceptance | job status panel', function (hooks) {

// Trigger a reschedule! Set up a desiredTransition object with a Reschedule property on one of the allocations.
assert
.dom(restartedCell.querySelector('.failed-or-lost-link'))
.dom(restartedCell)
.hasText(
'2',
'2 Restarted',
'Restarted cell updates when a second task event with type "Restarting" is added'
);

Expand All @@ -725,8 +725,11 @@ module('Acceptance | job status panel', function (hooks) {
await settled();

assert
.dom(rescheduledCell.querySelector('.failed-or-lost-link'))
.hasText('1', 'Rescheduled cell updates when desiredTransition is set');
.dom(rescheduledCell)
.hasText(
'1 Rescheduled',
'Rescheduled cell updates when desiredTransition is set'
);
assert
.dom(rescheduledCell.querySelector('a'))
.exists('Rescheduled cell with a non-zero number is now a link');
Expand Down Expand Up @@ -900,10 +903,10 @@ module('Acceptance | job status panel', function (hooks) {
await visit(`/jobs/${job.id}`);
assert.dom('.job-status-panel').exists();
assert.dom('.failed-or-lost').exists({ count: 1 });
assert.dom('.failed-or-lost h4').hasText('Restarted');
assert.dom('.failed-or-lost h4').hasText('Replaced Allocations');
assert
.dom('.failed-or-lost-link')
.hasText('0', 'Restarted cell at zero by default');
.dom('.failed-or-lost-links > span')
.hasText('0 Restarted', 'Restarted cell at zero by default');

// A wild event appears! Change a recent task event to type "Restarting" in a task state:
this.store
Expand All @@ -920,9 +923,9 @@ module('Acceptance | job status panel', function (hooks) {
await settled();

assert
.dom('.failed-or-lost-link')
.dom('.failed-or-lost-links > span')
.hasText(
'1',
'1 Restarted',
'Restarted cell updates when a task event with type "Restarting" is added'
);
});
Expand Down
Loading