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

System Batch UI, Client Status Bar Chart and Client Tab page view #11078

Merged
merged 66 commits into from
Oct 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
1f95a67
initial logic for computing client status bar
ChaiWithJai Aug 24, 2021
c4584e7
edit the schema of uniqueNodes returned by the controller
ChaiWithJai Aug 24, 2021
38f764f
refactoring job client status
lgfa29 Aug 24, 2021
29b107b
first implementation of job client status
lgfa29 Aug 24, 2021
051007d
small improvements to the jobClientStatus helper
lgfa29 Aug 26, 2021
42c6b91
display the right number in the client status bar
lgfa29 Aug 26, 2021
2c96d75
create client tab view
ChaiWithJai Aug 27, 2021
04e69f4
Merge remote-tracking branch 'origin/f-sysbatch-ui' into f-sysbatch-u…
lgfa29 Aug 27, 2021
3c50ac7
create sysbatch pages and components
lgfa29 Aug 27, 2021
91a17cb
add line break
lgfa29 Aug 27, 2021
aaac85a
Merge pull request #11094 from hashicorp/f-sysbatch-ui-luiz
ChaiWithJai Aug 30, 2021
6444f6a
filtering in client tab
ChaiWithJai Sep 1, 2021
c0171a4
svg link
ChaiWithJai Sep 2, 2021
d6dd911
refactor client-status-bar to append chart with links
ChaiWithJai Sep 7, 2021
2a2902d
unit test
ChaiWithJai Sep 8, 2021
d89d071
ui: policy system and sysbatch job details clients tab
lgfa29 Sep 10, 2021
ce3c517
client tab test
ChaiWithJai Sep 15, 2021
749828f
client tab test
ChaiWithJai Sep 15, 2021
7ad3e30
lint fixes
ChaiWithJai Sep 15, 2021
d4d6a8a
get all nodes if client tab is first page we land on
ChaiWithJai Sep 15, 2021
7a6db58
Merge branch 'f-sysbatch-ui' into f-sysbatch-ui-clients-tab
ChaiWithJai Sep 15, 2021
8f711a4
add whitespace
ChaiWithJai Sep 15, 2021
96a7e62
Merge pull request #11172 from hashicorp/f-sysbatch-ui-clients-tab
ChaiWithJai Sep 15, 2021
0453eaf
integration test for component
ChaiWithJai Sep 16, 2021
c57db19
acceptance tests for client tab
ChaiWithJai Sep 17, 2021
b727f37
ui: refactor job summary bar click
lgfa29 Sep 21, 2021
27d7a68
ui: set node watcher only if needed
lgfa29 Sep 21, 2021
9687a27
ui: rename some files and components
lgfa29 Sep 21, 2021
d5176f4
ui: only set pointer cursor if the slice has click event
lgfa29 Sep 21, 2021
7e7525f
ui: use existing style for empty job client status placeholder
lgfa29 Sep 21, 2021
00b53bb
ui: revert automatic changes to distribution-bar.hbs
lgfa29 Sep 21, 2021
d0f9108
ui: make job client status summary legend clickable
lgfa29 Sep 23, 2021
eb1bcb0
ui: small fixes
lgfa29 Sep 23, 2021
358a8a9
ui: add system and service jobs to sysbatchSmall mirage scenario
lgfa29 Sep 23, 2021
a7e3568
ui: lint
lgfa29 Sep 24, 2021
41e35bd
ui: rename job details client page node class filter for client class
lgfa29 Sep 24, 2021
081224e
ui: use links for short id in the job details client tab
lgfa29 Sep 24, 2021
6473b97
ui: fix sorting by id and name in the job details client tab
lgfa29 Sep 24, 2021
4ac392d
tmp
lgfa29 Sep 27, 2021
e331503
ui: fix pagination on job details client tab
lgfa29 Sep 28, 2021
619938f
ui: add TODO for job status client facet tests
lgfa29 Sep 28, 2021
5577d0d
ui: fix tests for job client status in job details page
lgfa29 Sep 29, 2021
c36396b
ui: fix linting
lgfa29 Sep 29, 2021
d19b8d7
ui: add help tooltip to summary bar legend
lgfa29 Sep 30, 2021
807a3eb
ui: add sysbatch as a job list filter option
lgfa29 Oct 4, 2021
f80d97f
ui: add parameterized and periodic sysbatch jobs to mirage
lgfa29 Oct 4, 2021
3f42a63
Merge remote-tracking branch 'origin/main' into f-sysbatch-ui
lgfa29 Oct 4, 2021
d5d069a
ui: fix merge
lgfa29 Oct 4, 2021
967c350
ui: force namespace query param in job details tabs
lgfa29 Oct 4, 2021
d6932bd
ui: filter out old allocations when computing job status in client
lgfa29 Oct 5, 2021
05e5f59
ui: remove some of the redundant help messages for job status in client
lgfa29 Oct 5, 2021
fa0d48a
ui: fix distribution bar click event listener
lgfa29 Oct 5, 2021
a8cd04a
edited dependent keys in job client status helper
ChaiWithJai Oct 5, 2021
6d7735d
Merge pull request #11266 from hashicorp/f-ui-node-watcher-bug
ChaiWithJai Oct 6, 2021
86a1e14
edit observable for node in job client status
ChaiWithJai Oct 6, 2021
91bb5b1
add conditional rendering logic for child jobs
ChaiWithJai Oct 6, 2021
15c9d82
Merge pull request #11275 from hashicorp/f-ui-client-update-bug
ChaiWithJai Oct 6, 2021
620b8d0
ui: fix job client status summary navigation for jobs with namespace
lgfa29 Oct 6, 2021
7ca852b
ui: add missing computed property dependency
lgfa29 Oct 6, 2021
452835d
refactor forceCollapsed logic to use hasClientStatus prop
ChaiWithJai Oct 6, 2021
7bb2478
Merge pull request #11281 from hashicorp/f-final-changes
ChaiWithJai Oct 6, 2021
309e599
ui: revert automated code formating
lgfa29 Oct 6, 2021
c38c0a5
ui: small fixes for job client status
lgfa29 Oct 7, 2021
dc22c75
ui: fix job-client-status bar tests
lgfa29 Oct 7, 2021
0dbf4a0
ui: fix child job client status slice click
lgfa29 Oct 7, 2021
8c8c3fd
ui: add job client status help message
lgfa29 Oct 7, 2021
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
16 changes: 13 additions & 3 deletions ui/.prettierrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
printWidth: 100
singleQuote: true
trailingComma: es5
{
"printWidth": 100,
"singleQuote": true,
"trailingComma": "es5",
"overrides": [
{
"files": "*.hbs",
"options": {
"singleQuote": false
}
}
]
}
4 changes: 3 additions & 1 deletion ui/app/components/allocation-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ export default class AllocationRow extends Component {
do {
if (this.stats) {
try {
yield this.get('stats.poll').perform();
yield this.get('stats.poll')
.linked()
.perform();
this.set('statsError', false);
} catch (error) {
this.set('statsError', true);
Expand Down
19 changes: 16 additions & 3 deletions ui/app/components/distribution-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const sumAggregate = (total, val) => total + val;
export default class DistributionBar extends Component.extend(WindowResizable) {
chart = null;
@overridable(() => null) data;
onSliceClick = null;
activeDatum = null;
isNarrow = false;

Expand All @@ -33,11 +34,13 @@ export default class DistributionBar extends Component.extend(WindowResizable) {
const data = copy(this.data, true);
const sum = data.mapBy('value').reduce(sumAggregate, 0);

return data.map(({ label, value, className, layers }, index) => ({
return data.map(({ label, value, className, layers, legendLink, help }, index) => ({
label,
value,
className,
layers,
legendLink,
help,
index,
percent: value / sum,
offset:
Expand Down Expand Up @@ -121,8 +124,14 @@ export default class DistributionBar extends Component.extend(WindowResizable) {
const activeDatum = this.activeDatum;
const isActive = activeDatum && activeDatum.label === d.label;
const isInactive = activeDatum && activeDatum.label !== d.label;
return [ className, isActive && 'active', isInactive && 'inactive' ].compact().join(' ');
});
const isClickable = !!this.onSliceClick;
return [
className,
isActive && 'active',
isInactive && 'inactive',
isClickable && 'clickable'
].compact().join(' ');
}).attr('data-test-slice-label', d => d.className);

this.set('slices', slices);

Expand Down Expand Up @@ -172,6 +181,10 @@ export default class DistributionBar extends Component.extend(WindowResizable) {
.attr('height', '6px')
.attr('y', '50%');
}

if (this.onSliceClick) {
slices.on('click', this.onSliceClick);
}
}
/* eslint-enable */

Expand Down
120 changes: 120 additions & 0 deletions ui/app/components/job-client-status-bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { computed } from '@ember/object';
import DistributionBar from './distribution-bar';
import classic from 'ember-classic-decorator';

@classic
export default class JobClientStatusBar extends DistributionBar {
layoutName = 'components/distribution-bar';

'data-test-job-client-status-bar' = true;
job = null;
jobClientStatus = null;

@computed('job.namespace', 'jobClientStatus.byStatus')
get data() {
const {
queued,
starting,
running,
complete,
degraded,
failed,
lost,
notScheduled,
} = this.jobClientStatus.byStatus;

return [
{
label: 'Queued',
value: queued.length,
className: 'queued',
legendLink: {
queryParams: {
status: JSON.stringify(['queued']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Starting',
value: starting.length,
className: 'starting',
legendLink: {
queryParams: {
status: JSON.stringify(['starting']),
namespace: this.job.namespace.get('id'),
},
},
layers: 2,
},
{
label: 'Running',
value: running.length,
className: 'running',
legendLink: {
queryParams: {
status: JSON.stringify(['running']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Complete',
value: complete.length,
className: 'complete',
legendLink: {
queryParams: {
status: JSON.stringify(['complete']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Degraded',
value: degraded.length,
className: 'degraded',
legendLink: {
queryParams: {
status: JSON.stringify(['degraded']),
namespace: this.job.namespace.get('id'),
},
},
help: 'Some allocations for this job were not successfull or did not run.',
},
{
label: 'Failed',
value: failed.length,
className: 'failed',
legendLink: {
queryParams: {
status: JSON.stringify(['failed']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Lost',
value: lost.length,
className: 'lost',
legendLink: {
queryParams: {
status: JSON.stringify(['lost']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Not Scheduled',
value: notScheduled.length,
className: 'not-scheduled',
legendLink: {
queryParams: {
status: JSON.stringify(['notScheduled']),
namespace: this.job.namespace.get('id'),
},
},
help: 'No allocations for this job were scheduled into these clients.',
},
];
}
}
89 changes: 89 additions & 0 deletions ui/app/components/job-client-status-row.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import EmberObject from '@ember/object';
import Component from '@glimmer/component';

export default class ClientRow extends Component {
// Attribute set in the template as @onClick.
onClick() {}

get row() {
return this.args.row.model;
}

get shouldDisplayAllocationSummary() {
return this.args.row.model.jobStatus !== 'notScheduled';
}

get allocationSummaryPlaceholder() {
switch (this.args.row.model.jobStatus) {
case 'notScheduled':
return 'Not Scheduled';
default:
return '';
}
}

get humanizedJobStatus() {
switch (this.args.row.model.jobStatus) {
case 'notScheduled':
return 'not scheduled';
default:
return this.args.row.model.jobStatus;
}
}

get jobStatusClass() {
switch (this.args.row.model.jobStatus) {
case 'notScheduled':
return 'not-scheduled';
default:
return this.args.row.model.jobStatus;
}
}

get allocationContainer() {
const statusSummary = {
queuedAllocs: 0,
completeAllocs: 0,
failedAllocs: 0,
runningAllocs: 0,
startingAllocs: 0,
lostAllocs: 0,
};

switch (this.args.row.model.jobStatus) {
case 'notSchedule':
break;
case 'queued':
statusSummary.queuedAllocs = this.args.row.model.allocations.length;
break;
case 'starting':
statusSummary.startingAllocs = this.args.row.model.allocations.length;
break;
default:
for (const alloc of this.args.row.model.allocations) {
switch (alloc.clientStatus) {
case 'running':
statusSummary.runningAllocs++;
break;
case 'lost':
statusSummary.lostAllocs++;
break;
case 'failed':
statusSummary.failedAllocs++;
break;
case 'complete':
statusSummary.completeAllocs++;
break;
case 'starting':
statusSummary.startingAllocs++;
break;
}
}
}

const Allocations = EmberObject.extend({
...statusSummary,
});
return Allocations.create();
}
}
9 changes: 9 additions & 0 deletions ui/app/components/job-page/parameterized-child.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import PeriodicChildJobPage from './periodic-child';
import classic from 'ember-classic-decorator';
import jobClientStatus from 'nomad-ui/utils/properties/job-client-status';

@classic
export default class ParameterizedChild extends PeriodicChildJobPage {
@alias('job.decodedPayload') payload;
@service store;

@computed('payload')
get payloadJSON() {
Expand All @@ -17,4 +20,10 @@ export default class ParameterizedChild extends PeriodicChildJobPage {
}
return json;
}

@jobClientStatus('nodes', 'job') jobClientStatus;

get nodes() {
return this.store.peekAll('node');
}
}
28 changes: 28 additions & 0 deletions ui/app/components/job-page/parts/job-client-status-summary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Component from '@ember/component';
import { action, computed } from '@ember/object';
import { classNames } from '@ember-decorators/component';
import classic from 'ember-classic-decorator';

@classic
@classNames('boxed-section')
export default class JobClientStatusSummary extends Component {
job = null;
jobClientStatus = null;
gotoClients() {}

@computed
get isExpanded() {
const storageValue = window.localStorage.nomadExpandJobClientStatusSummary;
return storageValue != null ? JSON.parse(storageValue) : true;
}

@action
onSliceClick(slice) {
this.gotoClients([slice.className.camelize()]);
}

persist(item, isOpen) {
window.localStorage.nomadExpandJobClientStatusSummary = isOpen;
this.notifyPropertyChange('isExpanded');
}
}
5 changes: 4 additions & 1 deletion ui/app/components/job-page/parts/summary.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import classic from 'ember-classic-decorator';
@classNames('boxed-section')
export default class Summary extends Component {
job = null;
forceCollapsed = false;

@computed
@computed('forceCollapsed')
get isExpanded() {
if (this.forceCollapsed) return false;

const storageValue = window.localStorage.nomadExpandJobSummary;
return storageValue != null ? JSON.parse(storageValue) : true;
}
Expand Down
10 changes: 10 additions & 0 deletions ui/app/components/job-page/periodic-child.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import AbstractJobPage from './abstract';
import { computed } from '@ember/object';
import { inject as service } from '@ember/service';
import classic from 'ember-classic-decorator';
import jobClientStatus from 'nomad-ui/utils/properties/job-client-status';

@classic
export default class PeriodicChild extends AbstractJobPage {
@service store;

@computed('job.{name,id}', 'job.parent.{name,id}')
get breadcrumbs() {
const job = this.job;
Expand All @@ -21,4 +25,10 @@ export default class PeriodicChild extends AbstractJobPage {
},
];
}

@jobClientStatus('nodes', 'job') jobClientStatus;

get nodes() {
return this.store.peekAll('node');
}
}
15 changes: 15 additions & 0 deletions ui/app/components/job-page/sysbatch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import AbstractJobPage from './abstract';
import classic from 'ember-classic-decorator';
import { inject as service } from '@ember/service';
import jobClientStatus from 'nomad-ui/utils/properties/job-client-status';

@classic
export default class Sysbatch extends AbstractJobPage {
@service store;

@jobClientStatus('nodes', 'job') jobClientStatus;

get nodes() {
return this.store.peekAll('node');
}
}
Loading