Skip to content

Commit

Permalink
ui: node pools - add pool count to topology visualization (#17363)
Browse files Browse the repository at this point in the history
* chore: create pool adapter

* chore: mirage route handler

* ui: add pool count to topo

* ui:  node pools data on `jobs.index` page (#17368)

* ui: node filter on jobs.index

* ui: add node pool to table viz

* ui:  node pools - client page visualization (#17372)

* refact: update mirage models

* ui: add pool filter to client list

* ui:  add pool to table viz

* ui:  add pool to statsboxes (#17373)
  • Loading branch information
ChaiWithJai authored and lgfa29 committed Jun 22, 2023
1 parent 126d2e5 commit 17bcf57
Show file tree
Hide file tree
Showing 21 changed files with 154 additions and 41 deletions.
19 changes: 19 additions & 0 deletions ui/app/adapters/node-pool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import ApplicationAdapter from './application';
import classic from 'ember-classic-decorator';
import { pluralize } from 'ember-inflector';

@classic
export default class NodePoolAdapter extends ApplicationAdapter {
urlForFindAll(modelName) {
let [relationshipResource, resource] = modelName.split('-');
resource = pluralize(resource);
const baseUrl = `/v1/${relationshipResource}/${resource}`;

return baseUrl;
}
}
33 changes: 33 additions & 0 deletions ui/app/controllers/clients/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ export default class IndexController extends Controller.extend(
{
qpVolume: 'volume',
},
{
qpNodePool: 'nodePool',
},
];

currentPage = 1;
Expand All @@ -75,12 +78,14 @@ export default class IndexController extends Controller.extend(
qpDatacenter = '';
qpVersion = '';
qpVolume = '';
qpNodePool = '';

@selection('qpClass') selectionClass;
@selection('qpState') selectionState;
@selection('qpDatacenter') selectionDatacenter;
@selection('qpVersion') selectionVersion;
@selection('qpVolume') selectionVolume;
@selection('qpNodePool') selectionNodePools;

@computed('nodes.[]', 'selectionClass')
get optionsClass() {
Expand Down Expand Up @@ -164,11 +169,35 @@ export default class IndexController extends Controller.extend(
return volumes.sort().map((volume) => ({ key: volume, label: volume }));
}

@computed('selectionNodePools', 'model.nodePools.[]')
get optionsNodePools() {
const availableNodePools = this.model.nodePools;

scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
this.set(
'qpNodePool',
serialize(
intersection(
availableNodePools.map(({ name }) => name),
this.selectionNodePools
)
)
);
});

return availableNodePools.map((nodePool) => ({
key: nodePool.name,
label: nodePool.name,
}));
}

@computed(
'nodes.[]',
'selectionClass',
'selectionState',
'selectionDatacenter',
'selectionNodePools',
'selectionVersion',
'selectionVolume'
)
Expand All @@ -177,6 +206,7 @@ export default class IndexController extends Controller.extend(
selectionClass: classes,
selectionState: states,
selectionDatacenter: datacenters,
selectionNodePools: nodePools,
selectionVersion: versions,
selectionVolume: volumes,
} = this;
Expand All @@ -201,6 +231,9 @@ export default class IndexController extends Controller.extend(
!node.hostVolumes.find((volume) => volumes.includes(volume.name))
)
return false;
if (nodePools.length && !nodePools.includes(node.get('nodePool'))) {
return false;
}

if (onlyIneligible && node.get('isEligible')) return false;
if (onlyDraining && !node.get('isDraining')) return false;
Expand Down
34 changes: 34 additions & 0 deletions ui/app/controllers/jobs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ export default class IndexController extends Controller.extend(
{
qpNamespace: 'namespace',
},
{
qpNodePool: 'nodePool',
},
];

currentPage = 1;
Expand All @@ -81,11 +84,13 @@ export default class IndexController extends Controller.extend(
qpStatus = '';
qpDatacenter = '';
qpPrefix = '';
qpNodePool = '';

@selection('qpType') selectionType;
@selection('qpStatus') selectionStatus;
@selection('qpDatacenter') selectionDatacenter;
@selection('qpPrefix') selectionPrefix;
@selection('qpNodePool') selectionNodePools;

@computed
get optionsType() {
Expand Down Expand Up @@ -194,6 +199,29 @@ export default class IndexController extends Controller.extend(
return availableNamespaces;
}

@computed('selectionNodePools', 'model.nodePools.[]')
get optionsNodePools() {
const availableNodePools = this.model.nodePools;

scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
this.set(
'qpNodePool',
serialize(
intersection(
availableNodePools.map(({ name }) => name),
this.selectionNodePools
)
)
);
});

return availableNodePools.map((nodePool) => ({
key: nodePool.name,
label: nodePool.name,
}));
}

/**
Visible jobs are those that match the selected namespace and aren't children
of periodic or parameterized jobs.
Expand All @@ -212,6 +240,7 @@ export default class IndexController extends Controller.extend(
'selectionType',
'selectionStatus',
'selectionDatacenter',
'selectionNodePools',
'selectionPrefix'
)
get filteredJobs() {
Expand All @@ -220,6 +249,7 @@ export default class IndexController extends Controller.extend(
selectionStatus: statuses,
selectionDatacenter: datacenters,
selectionPrefix: prefixes,
selectionNodePools: nodePools,
} = this;

// A job must match ALL filter facets, but it can match ANY selection within a facet
Expand All @@ -246,6 +276,10 @@ export default class IndexController extends Controller.extend(
return false;
}

if (nodePools.length && !nodePools.includes(job.get('nodePool'))) {
return false;
}

const name = job.get('name');
if (
prefixes.length &&
Expand Down
3 changes: 1 addition & 2 deletions ui/app/models/node-pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import Model from '@ember-data/model';
import { attr, hasMany } from '@ember-data/model';
import { attr } from '@ember-data/model';
import { computed } from '@ember/object';
import classic from 'ember-classic-decorator';

Expand All @@ -14,7 +14,6 @@ export default class NodePool extends Model {
@attr('string') description;
@attr() meta;
@attr() schedulerConfiguration;
@hasMany('node') nodes;

@computed('schedulerConfiguration.SchedulerAlgorithm')
get schedulerAlgorithm() {
Expand Down
4 changes: 2 additions & 2 deletions ui/app/models/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { computed } from '@ember/object';
import { equal } from '@ember/object/computed';
import Model from '@ember-data/model';
import { attr } from '@ember-data/model';
import { belongsTo, hasMany } from '@ember-data/model';
import { hasMany } from '@ember-data/model';
import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes';
import RSVP from 'rsvp';
import shortUUIDProperty from '../utils/properties/short-uuid';
Expand All @@ -27,6 +27,7 @@ export default class Node extends Model {
@shortUUIDProperty('id') shortId;
@attr('number') modifyIndex;
@attr('string') version;
@attr('string') nodePool;

// Available from single response
@attr('string') httpAddr;
Expand Down Expand Up @@ -55,7 +56,6 @@ export default class Node extends Model {
}

@hasMany('allocations', { inverse: 'node' }) allocations;
@belongsTo('node-pool') nodePool;

@computed('allocations.@each.clientStatus')
get completeAllocations() {
Expand Down
1 change: 1 addition & 0 deletions ui/app/routes/clients.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default class ClientsRoute extends Route.extend(WithForbiddenState) {
return RSVP.hash({
nodes: this.store.findAll('node'),
agents: this.store.findAll('agent'),
nodePools: this.store.findAll('node-pool'),
}).catch(notifyForbidden(this));
}
}
1 change: 1 addition & 0 deletions ui/app/routes/jobs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default class IndexRoute extends Route.extend(
.query('job', { namespace: params.qpNamespace, meta: true })
.catch(notifyForbidden(this)),
namespaces: this.store.findAll('namespace'),
nodePools: this.store.findAll('node-pool'),
});
}

Expand Down
2 changes: 2 additions & 0 deletions ui/app/routes/topology.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default class TopologyRoute extends Route.extend(WithForbiddenState) {
namespace: '*',
}),
nodes: this.store.query('node', { resources: true }),
nodePools: this.store.findAll('node-pool'),
}).catch(notifyForbidden(this));
}

Expand All @@ -32,6 +33,7 @@ export default class TopologyRoute extends Route.extend(WithForbiddenState) {
controller.model = {
allocations: [],
nodes: [],
nodePools: [],
};
}

Expand Down
6 changes: 6 additions & 0 deletions ui/app/styles/components/dashboard-metric.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
font-weight: $weight-bold;
font-size: $size-3;

&.topo {
display: flex;
flex-direction: column;
align-items: center;
}

.metric-units {
font-size: $size-4;
}
Expand Down
8 changes: 8 additions & 0 deletions ui/app/templates/clients/client/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,14 @@
</span>
{{this.model.datacenter}}
</span>
{{#if this.model.nodePool}}
<span class="pair" data-test-node-pool>
<span class="term">
Node Pool
</span>
{{this.model.nodePool}}
</span>
{{/if}}
{{#if this.model.nodeClass}}
<span class="pair" data-test-node-class>
<span class="term">
Expand Down
8 changes: 8 additions & 0 deletions ui/app/templates/clients/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
@selection={{this.selectionClass}}
@onSelect={{action this.setFacetQueryParam "qpClass"}}
/>
<MultiSelectDropdown
data-test-node-pool-facet
@label="Node Pool"
@options={{this.optionsNodePools}}
@selection={{this.selectionNodePools}}
@onSelect={{action this.setFacetQueryParam "qpNodePool"}}
/>
<MultiSelectDropdown
data-test-state-facet
@label="State"
Expand Down Expand Up @@ -79,6 +86,7 @@
@class="is-200px is-truncatable"
@prop="name"
>Name</t.sort-by>
<t.sort-by @prop="nodePool">Node Pool</t.sort-by>
<t.sort-by @prop="compositeStatus">State</t.sort-by>
<th class="is-200px is-truncatable">Address</th>
<t.sort-by @prop="datacenter">Datacenter</t.sort-by>
Expand Down
1 change: 1 addition & 0 deletions ui/app/templates/components/client-node-row.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
</td>
<td data-test-client-id><LinkTo @route="clients.client" @model={{this.node.id}} class="is-primary">{{this.node.shortId}}</LinkTo></td>
<td data-test-client-name class="is-200px is-truncatable" title="{{this.node.name}}">{{this.node.name}}</td>
<td data-test-client-nodepool title="{{this.node.nodePool}}">{{this.node.nodePool}}</td>
<td data-test-client-composite-status>
<span class="tooltip" aria-label="{{this.node.status}} / {{if this.node.isDraining "draining" "not draining"}} / {{if this.node.isEligible "eligible" "not eligible"}}">
<span class="{{this.compositeStatusClass}}">{{this.node.compositeStatus}}</span>
Expand Down
6 changes: 6 additions & 0 deletions ui/app/templates/components/job-page/parts/stats-box.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
{{@job.namespace.name}}
</span>
{{/if}}
{{#if @job.nodePool}}
<span class="pair" data-test-job-stat="nodePool">
<span class="term">Node Pool</span>
{{@job.nodePool}}
</span>
{{/if}}
{{yield to="after-namespace"}}
</div>

Expand Down
3 changes: 3 additions & 0 deletions ui/app/templates/components/job-row.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
</td>
{{/if}}
{{/if}}
<td data-test-job-nodepool>
{{this.job.nodePool}}
</td>
{{#if (eq @context "child")}}
<td data-test-job-submit-time>
{{format-month-ts this.job.submitTime}}
Expand Down
10 changes: 10 additions & 0 deletions ui/app/templates/jobs/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@
@selection={{this.selectionType}}
@onSelect={{action this.setFacetQueryParam "qpType"}}
/>
<MultiSelectDropdown
data-test-node-pool-facet
@label="Node Pool"
@options={{this.optionsNodePools}}
@selection={{this.selectionNodePools}}
@onSelect={{action this.setFacetQueryParam "qpNodePool"}}
/>
<MultiSelectDropdown
data-test-status-facet
@label="Status"
Expand Down Expand Up @@ -136,6 +143,9 @@
Namespace
</t.sort-by>
{{/if}}
<t.sort-by @prop="nodePool">
Node Pool
</t.sort-by>
<t.sort-by @prop="status">
Status
</t.sort-by>
Expand Down
12 changes: 10 additions & 2 deletions ui/app/templates/topology.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -370,21 +370,29 @@
{{else}}
<div class="columns is-flush">
<div class="dashboard-metric column">
<p data-test-node-count class="metric">
<p data-test-node-count class="metric topo">
{{this.model.nodes.length}}
<span class="metric-label">
Clients
</span>
</p>
</div>
<div class="dashboard-metric column">
<p data-test-alloc-count class="metric">
<p data-test-alloc-count class="metric topo">
{{this.scheduledAllocations.length}}
<span class="metric-label">
Allocations
</span>
</p>
</div>
<div class="dashboard-metric column">
<p data-test-node-pool-count class="metric topo">
{{this.model.nodePools.length}}
<span class="metric-label">
Node Pools
</span>
</p>
</div>
</div>
<div class="dashboard-metric with-divider">
<p class="metric">
Expand Down
Loading

0 comments on commit 17bcf57

Please sign in to comment.