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: display Nomad version in the Clients and Servers table #11366

Merged
merged 6 commits into from
Oct 22, 2021
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 3 additions & 0 deletions .changelog/11366.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
ui: Display the Nomad version in the Servers and Clients tables and allow filtering and sorting
```
23 changes: 22 additions & 1 deletion ui/app/controllers/clients/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import classic from 'ember-classic-decorator';

@classic
export default class IndexController extends Controller.extend(
SortableFactory(['id', 'name', 'compositeStatus', 'datacenter']),
SortableFactory(['id', 'name', 'compositeStatus', 'datacenter', 'version']),
Searchable
) {
@service userSettings;
Expand Down Expand Up @@ -43,6 +43,9 @@ export default class IndexController extends Controller.extend(
{
qpDatacenter: 'dc',
},
{
qpVersion: 'version',
},
{
qpVolume: 'volume',
},
Expand All @@ -62,11 +65,13 @@ export default class IndexController extends Controller.extend(
qpClass = '';
qpState = '';
qpDatacenter = '';
qpVersion = '';
qpVolume = '';

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

@computed('nodes.[]', 'selectionClass')
Expand Down Expand Up @@ -108,6 +113,19 @@ export default class IndexController extends Controller.extend(
return datacenters.sort().map(dc => ({ key: dc, label: dc }));
}

@computed('nodes.[]', 'selectionVersion')
get optionsVersion() {
const versions = Array.from(new Set(this.nodes.mapBy('version'))).compact();

// Remove any invalid datacenters from the query param/selection
lgfa29 marked this conversation as resolved.
Show resolved Hide resolved
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
this.set('qpVersion', serialize(intersection(versions, this.selectionVersion)));
});

return versions.sort().map(v => ({ key: v, label: v }));
}

@computed('nodes.[]', 'selectionVolume')
get optionsVolume() {
const flatten = (acc, val) => acc.concat(val.toArray());
Expand All @@ -128,13 +146,15 @@ export default class IndexController extends Controller.extend(
'selectionClass',
'selectionState',
'selectionDatacenter',
'selectionVersion',
'selectionVolume'
)
get filteredNodes() {
const {
selectionClass: classes,
selectionState: states,
selectionDatacenter: datacenters,
selectionVersion: versions,
selectionVolume: volumes,
} = this;

Expand All @@ -148,6 +168,7 @@ export default class IndexController extends Controller.extend(
if (classes.length && !classes.includes(node.get('nodeClass'))) return false;
if (statuses.length && !statuses.includes(node.get('status'))) return false;
if (datacenters.length && !datacenters.includes(node.get('datacenter'))) return false;
if (versions.length && !versions.includes(node.get('version'))) return false;
if (volumes.length && !node.hostVolumes.find(volume => volumes.includes(volume.name)))
return false;

Expand Down
5 changes: 5 additions & 0 deletions ui/app/models/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ export default class Agent extends Model {
get isLeader() {
return this.get('system.leader.rpcAddr') === this.rpcAddr;
}

@computed('tags.build')
get version() {
return this.tags?.build || '';
}
}
1 change: 1 addition & 0 deletions ui/app/models/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default class Node extends Model {
@attr('string') statusDescription;
@shortUUIDProperty('id') shortId;
@attr('number') modifyIndex;
@attr('string') version;

// Available from single response
@attr('string') httpAddr;
Expand Down
9 changes: 8 additions & 1 deletion ui/app/templates/clients/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
@options={{this.optionsDatacenter}}
@selection={{this.selectionDatacenter}}
@onSelect={{action this.setFacetQueryParam "qpDatacenter"}} />
<MultiSelectDropdown
data-test-version-facet
@label="Version"
@options={{this.optionsVersion}}
@selection={{this.selectionVersion}}
@onSelect={{action this.setFacetQueryParam "qpVersion"}} />
<MultiSelectDropdown
data-test-volume-facet
@label="Volume"
Expand All @@ -56,8 +62,9 @@
<t.sort-by @prop="id">ID</t.sort-by>
<t.sort-by @class="is-200px is-truncatable" @prop="name">Name</t.sort-by>
<t.sort-by @prop="compositeStatus">State</t.sort-by>
<th>Address</th>
<th class="is-200px is-truncatable">Address</th>
<t.sort-by @prop="datacenter">Datacenter</t.sort-by>
<t.sort-by @prop="version">Version</t.sort-by>
<th># Volumes</th>
<th># Allocs</th>
</t.head>
Expand Down
3 changes: 2 additions & 1 deletion ui/app/templates/components/client-node-row.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
<span class="{{this.compositeStatusClass}}">{{this.node.compositeStatus}}</span>
</span>
</td>
<td data-test-client-address>{{this.node.httpAddr}}</td>
<td data-test-client-address class="is-200px is-truncatable">{{this.node.httpAddr}}</td>
<td data-test-client-datacenter>{{this.node.datacenter}}</td>
<td data-test-client-version>{{this.node.version}}</td>
<td data-test-client-volumes>{{if this.node.hostVolumes.length this.node.hostVolumes.length}}</td>
<td data-test-client-allocations>
{{#if this.node.allocations.isPending}}
Expand Down
3 changes: 2 additions & 1 deletion ui/app/templates/components/server-agent-row.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<td data-test-server-name><LinkTo @route="servers.server" @model={{this.agent.id}} class="is-primary">{{this.agent.name}}</LinkTo></td>
<td data-test-server-status>{{this.agent.status}}</td>
<td data-test-server-is-leader>{{if this.agent.isLeader "True" "False"}}</td>
<td data-test-server-address>{{this.agent.address}}</td>
<td data-test-server-address class="is-200px is-truncatable">{{this.agent.address}}</td>
<td data-test-server-port>{{this.agent.serfPort}}</td>
<td data-test-server-datacenter>{{this.agent.datacenter}}</td>
<td data-test-server-version>{{this.agent.version}}</td>
3 changes: 2 additions & 1 deletion ui/app/templates/servers/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
<t.sort-by @prop="name">Name</t.sort-by>
<t.sort-by @prop="status">Status</t.sort-by>
<t.sort-by @prop="isLeader">Leader</t.sort-by>
<t.sort-by @prop="address">Address</t.sort-by>
<t.sort-by @class="is-200px is-truncatable" @prop="address">Address</t.sort-by>
<t.sort-by @prop="serfPort">port</t.sort-by>
<t.sort-by @prop="datacenter">Datacenter</t.sort-by>
<t.sort-by @prop="version">Version</t.sort-by>
</t.head>
<t.body as |row|>
<ServerAgentRow data-test-server-agent-row @agent={{row.model}} />
Expand Down
6 changes: 6 additions & 0 deletions ui/mirage/factories/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { DATACENTERS } from '../common';

const UUIDS = provide(100, faker.random.uuid.bind(faker.random));
const AGENT_STATUSES = ['alive', 'leaving', 'left', 'failed'];
const AGENT_BUILDS = ['1.1.0-beta', '1.0.2-alpha+ent', ...provide(5, faker.system.semver)];

export default Factory.extend({
id: i => (i / 100 >= 1 ? `${UUIDS[i]}-${i}` : UUIDS[i]),
Expand All @@ -29,6 +30,10 @@ export default Factory.extend({
Tags: generateTags(serfPort),
};
},

version() {
return this.member.Tags?.build || '';
},
});

function generateName() {
Expand All @@ -44,5 +49,6 @@ function generateTags(serfPort) {
return {
port: rpcPortCandidate === serfPort ? rpcPortCandidate + 1 : rpcPortCandidate,
dc: faker.helpers.randomize(DATACENTERS),
build: faker.helpers.randomize(AGENT_BUILDS),
};
}
2 changes: 2 additions & 0 deletions ui/mirage/factories/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import moment from 'moment';
const UUIDS = provide(100, faker.random.uuid.bind(faker.random));
const NODE_STATUSES = ['initializing', 'ready', 'down'];
const NODE_CLASSES = provide(7, faker.company.bsBuzz.bind(faker.company));
const NODE_VERSIONS = ['1.1.0-beta', '1.0.2-alpha+ent', ...provide(5, faker.system.semver)];
const REF_DATE = new Date();

export default Factory.extend({
Expand All @@ -22,6 +23,7 @@ export default Factory.extend({

createIndex: i => i,
modifyIndex: () => faker.random.number({ min: 10, max: 2000 }),
version: () => faker.helpers.randomize(NODE_VERSIONS),

httpAddr() {
return this.name.split('@')[1];
Expand Down
23 changes: 22 additions & 1 deletion ui/tests/acceptance/clients-list-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ module('Acceptance | clients list', function(hooks) {
);
assert.equal(nodeRow.address, node.httpAddr);
assert.equal(nodeRow.datacenter, node.datacenter, 'Datacenter');
assert.equal(nodeRow.version, node.version, 'Version');
assert.equal(nodeRow.allocations, allocations.length, '# Allocations');
});

Expand Down Expand Up @@ -146,7 +147,11 @@ module('Acceptance | clients list', function(hooks) {

assert.equal(ClientsList.nodes[1].compositeStatus.text, 'initializing');
assert.equal(ClientsList.nodes[2].compositeStatus.text, 'down');
assert.equal(ClientsList.nodes[2].compositeStatus.text, 'down', 'down takes priority over ineligible');
assert.equal(
ClientsList.nodes[2].compositeStatus.text,
'down',
'down takes priority over ineligible'
);

assert.equal(ClientsList.nodes[4].compositeStatus.text, 'ineligible');
assert.ok(ClientsList.nodes[4].compositeStatus.isWarning, 'expected warning class');
Expand Down Expand Up @@ -299,6 +304,22 @@ module('Acceptance | clients list', function(hooks) {
filter: (node, selection) => selection.includes(node.datacenter),
});

testFacet('Versions', {
facet: ClientsList.facets.version,
paramName: 'version',
expectedOptions(nodes) {
return Array.from(new Set(nodes.mapBy('version'))).sort();
},
async beforeEach() {
server.create('agent');
server.createList('node', 2, { version: '0.12.0' });
server.createList('node', 2, { version: '1.1.0-beta1' });
server.createList('node', 2, { version: '1.2.0+ent' });
await ClientsList.visit();
},
filter: (node, selection) => selection.includes(node.version),
});

testFacet('Volumes', {
facet: ClientsList.facets.volume,
paramName: 'volume',
Expand Down
1 change: 1 addition & 0 deletions ui/tests/acceptance/servers-list-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ module('Acceptance | servers list', function(hooks) {
assert.equal(agentRow.address, agent.member.Address, 'Address');
assert.equal(agentRow.serfPort, agent.member.Port, 'Serf Port');
assert.equal(agentRow.datacenter, agent.member.Tags.dc, 'Datacenter');
assert.equal(agentRow.version, agent.version, 'Version');
});

test('each server should link to the server detail page', async function(assert) {
Expand Down
2 changes: 2 additions & 0 deletions ui/tests/pages/clients/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default create({

address: text('[data-test-client-address]'),
datacenter: text('[data-test-client-datacenter]'),
version: text('[data-test-client-version]'),
allocations: text('[data-test-client-allocations]'),

clickRow: clickable(),
Expand All @@ -75,6 +76,7 @@ export default create({
class: multiFacet('[data-test-class-facet]'),
state: multiFacet('[data-test-state-facet]'),
datacenter: multiFacet('[data-test-datacenter-facet]'),
version: multiFacet('[data-test-version-facet]'),
volume: multiFacet('[data-test-volume-facet]'),
},
});
1 change: 1 addition & 0 deletions ui/tests/pages/servers/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default create({
address: text('[data-test-server-address]'),
serfPort: text('[data-test-server-port]'),
datacenter: text('[data-test-server-datacenter]'),
version: text('[data-test-server-version]'),

clickRow: clickable(),
clickName: clickable('[data-test-server-name] a'),
Expand Down