2017-09-26 07:47:16 +00:00
|
|
|
import Ember from 'ember';
|
2017-10-02 19:44:07 +00:00
|
|
|
import { click, find, findAll, fillIn, currentURL, visit } from 'ember-native-dom-helpers';
|
2017-09-19 14:47:10 +00:00
|
|
|
import { test } from 'qunit';
|
|
|
|
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
|
2017-10-17 01:47:25 +00:00
|
|
|
import { formatBytes } from 'nomad-ui/helpers/format-bytes';
|
2017-09-19 14:47:10 +00:00
|
|
|
|
2017-09-26 07:47:16 +00:00
|
|
|
const { $ } = Ember;
|
|
|
|
|
2017-09-19 14:47:10 +00:00
|
|
|
let job;
|
|
|
|
let taskGroup;
|
|
|
|
let tasks;
|
|
|
|
let allocations;
|
|
|
|
|
|
|
|
const sum = (total, n) => total + n;
|
|
|
|
|
|
|
|
moduleForAcceptance('Acceptance | task group detail', {
|
|
|
|
beforeEach() {
|
2017-09-26 01:13:58 +00:00
|
|
|
server.create('agent');
|
2017-09-19 14:47:10 +00:00
|
|
|
server.create('node', 'forceIPv4');
|
|
|
|
|
|
|
|
job = server.create('job', {
|
|
|
|
groupsCount: 2,
|
|
|
|
createAllocations: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
const taskGroups = server.db.taskGroups.where({ jobId: job.id });
|
|
|
|
taskGroup = taskGroups[0];
|
|
|
|
|
|
|
|
tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
|
|
|
|
|
|
|
|
server.create('node', 'forceIPv4');
|
|
|
|
|
|
|
|
allocations = server.createList('allocation', 2, {
|
|
|
|
jobId: job.id,
|
|
|
|
taskGroup: taskGroup.name,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Allocations associated to a different task group on the job to
|
|
|
|
// assert that they aren't showing up in on this page in error.
|
|
|
|
server.createList('allocation', 3, {
|
|
|
|
jobId: job.id,
|
|
|
|
taskGroup: taskGroups[1].name,
|
|
|
|
});
|
|
|
|
|
2017-10-02 19:44:07 +00:00
|
|
|
// Set a static name to make the search test deterministic
|
|
|
|
server.db.allocations.forEach(alloc => {
|
|
|
|
alloc.name = 'aaaaa';
|
|
|
|
});
|
|
|
|
|
2017-09-19 14:47:10 +00:00
|
|
|
visit(`/jobs/${job.id}/${taskGroup.name}`);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
test('/jobs/:id/:task-group should list high-level metrics for the allocation', function(assert) {
|
|
|
|
const totalCPU = tasks.mapBy('Resources.CPU').reduce(sum, 0);
|
|
|
|
const totalMemory = tasks.mapBy('Resources.MemoryMB').reduce(sum, 0);
|
|
|
|
const totalDisk = taskGroup.ephemeralDisk.SizeMB;
|
|
|
|
|
|
|
|
assert.equal(
|
2017-09-26 07:47:16 +00:00
|
|
|
findAll('.inline-definitions .pair')[0].textContent,
|
2017-09-19 14:47:10 +00:00
|
|
|
`# Tasks ${tasks.length}`,
|
|
|
|
'# Tasks'
|
|
|
|
);
|
|
|
|
assert.equal(
|
2017-09-26 07:47:16 +00:00
|
|
|
findAll('.inline-definitions .pair')[1].textContent,
|
2017-09-19 14:47:10 +00:00
|
|
|
`Reserved CPU ${totalCPU} MHz`,
|
|
|
|
'Aggregated CPU reservation for all tasks'
|
|
|
|
);
|
|
|
|
assert.equal(
|
2017-09-26 07:47:16 +00:00
|
|
|
findAll('.inline-definitions .pair')[2].textContent,
|
2017-09-19 14:47:10 +00:00
|
|
|
`Reserved Memory ${totalMemory} MiB`,
|
|
|
|
'Aggregated Memory reservation for all tasks'
|
|
|
|
);
|
|
|
|
assert.equal(
|
2017-09-26 07:47:16 +00:00
|
|
|
findAll('.inline-definitions .pair')[3].textContent,
|
2017-09-19 14:47:10 +00:00
|
|
|
`Reserved Disk ${totalDisk} MiB`,
|
|
|
|
'Aggregated Disk reservation for all tasks'
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('/jobs/:id/:task-group should have breadcrumbs for job and jobs', function(assert) {
|
2017-10-23 17:30:11 +00:00
|
|
|
assert.equal(findAll('.breadcrumb')[0].textContent.trim(), 'Jobs', 'First breadcrumb says jobs');
|
2017-09-26 07:47:16 +00:00
|
|
|
assert.equal(
|
2017-10-23 17:30:11 +00:00
|
|
|
findAll('.breadcrumb')[1].textContent.trim(),
|
2017-09-26 07:47:16 +00:00
|
|
|
job.name,
|
|
|
|
'Second breadcrumb says the job name'
|
|
|
|
);
|
2017-09-19 14:47:10 +00:00
|
|
|
assert.equal(
|
2017-10-23 17:30:11 +00:00
|
|
|
findAll('.breadcrumb')[2].textContent.trim(),
|
2017-09-19 14:47:10 +00:00
|
|
|
taskGroup.name,
|
|
|
|
'Third breadcrumb says the job name'
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('/jobs/:id/:task-group first breadcrumb should link to jobs', function(assert) {
|
2017-09-26 07:47:16 +00:00
|
|
|
click(findAll('.breadcrumb')[0]);
|
2017-09-19 14:47:10 +00:00
|
|
|
andThen(() => {
|
|
|
|
assert.equal(currentURL(), '/jobs', 'First breadcrumb links back to jobs');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('/jobs/:id/:task-group second breadcrumb should link to the job for the task group', function(
|
|
|
|
assert
|
|
|
|
) {
|
2017-09-26 07:47:16 +00:00
|
|
|
click(findAll('.breadcrumb')[1]);
|
2017-09-19 14:47:10 +00:00
|
|
|
andThen(() => {
|
|
|
|
assert.equal(
|
|
|
|
currentURL(),
|
|
|
|
`/jobs/${job.id}`,
|
|
|
|
'Second breadcrumb links back to the job for the task group'
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('/jobs/:id/:task-group should list one page of allocations for the task group', function(
|
|
|
|
assert
|
|
|
|
) {
|
|
|
|
const pageSize = 10;
|
|
|
|
|
|
|
|
server.createList('allocation', 10, {
|
|
|
|
jobId: job.id,
|
|
|
|
taskGroup: taskGroup.name,
|
|
|
|
});
|
|
|
|
|
|
|
|
visit('/jobs');
|
|
|
|
visit(`/jobs/${job.id}/${taskGroup.name}`);
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.ok(
|
|
|
|
server.db.allocations.where({ jobId: job.id }).length > pageSize,
|
|
|
|
'There are enough allocations to invoke pagination'
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.equal(
|
2017-09-26 07:47:16 +00:00
|
|
|
findAll('.allocations tbody tr').length,
|
2017-09-19 14:47:10 +00:00
|
|
|
pageSize,
|
|
|
|
'All allocations for the task group'
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('each allocation should show basic information about the allocation', function(assert) {
|
2017-10-18 02:19:02 +00:00
|
|
|
const allocation = allocations.sortBy('modifyIndex').reverse()[0];
|
2017-09-26 07:47:16 +00:00
|
|
|
const allocationRow = $(findAll('.allocations tbody tr')[0]);
|
2017-09-19 14:47:10 +00:00
|
|
|
|
2017-10-18 02:19:02 +00:00
|
|
|
andThen(() => {
|
|
|
|
assert.equal(
|
|
|
|
allocationRow
|
|
|
|
.find('td:eq(0)')
|
|
|
|
.text()
|
|
|
|
.trim(),
|
|
|
|
allocation.id.split('-')[0],
|
|
|
|
'Allocation short id'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
allocationRow
|
|
|
|
.find('td:eq(1)')
|
|
|
|
.text()
|
|
|
|
.trim(),
|
|
|
|
allocation.modifyIndex,
|
|
|
|
'Allocation modify index'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
allocationRow
|
|
|
|
.find('td:eq(2)')
|
|
|
|
.text()
|
|
|
|
.trim(),
|
|
|
|
allocation.name,
|
|
|
|
'Allocation name'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
allocationRow
|
|
|
|
.find('td:eq(3)')
|
|
|
|
.text()
|
|
|
|
.trim(),
|
|
|
|
allocation.clientStatus,
|
|
|
|
'Client status'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
allocationRow
|
|
|
|
.find('td:eq(4)')
|
|
|
|
.text()
|
|
|
|
.trim(),
|
2017-10-18 19:29:33 +00:00
|
|
|
allocation.jobVersion,
|
|
|
|
'Job Version'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
allocationRow
|
|
|
|
.find('td:eq(5)')
|
|
|
|
.text()
|
|
|
|
.trim(),
|
2017-10-18 02:19:02 +00:00
|
|
|
server.db.nodes.find(allocation.nodeId).id.split('-')[0],
|
|
|
|
'Node ID'
|
|
|
|
);
|
|
|
|
});
|
2017-09-26 01:13:58 +00:00
|
|
|
|
2017-10-18 19:29:33 +00:00
|
|
|
click(allocationRow.find('td:eq(5) a').get(0));
|
2017-09-26 01:13:58 +00:00
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.equal(currentURL(), `/nodes/${allocation.nodeId}`, 'Node links to node page');
|
|
|
|
});
|
2017-09-19 14:47:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
test('each allocation should show stats about the allocation, retrieved directly from the node', function(
|
|
|
|
assert
|
|
|
|
) {
|
|
|
|
const allocation = allocations.sortBy('name')[0];
|
2017-09-26 07:47:16 +00:00
|
|
|
const allocationRow = $(findAll('.allocations tbody tr')[0]);
|
2017-09-19 14:47:10 +00:00
|
|
|
const allocStats = server.db.clientAllocationStats.find(allocation.id);
|
|
|
|
const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
|
|
|
|
|
2017-10-17 01:47:25 +00:00
|
|
|
const cpuUsed = tasks.reduce((sum, task) => sum + task.Resources.CPU, 0);
|
|
|
|
const memoryUsed = tasks.reduce((sum, task) => sum + task.Resources.MemoryMB, 0);
|
|
|
|
|
2017-09-19 14:47:10 +00:00
|
|
|
assert.equal(
|
|
|
|
allocationRow
|
2017-10-18 19:29:33 +00:00
|
|
|
.find('td:eq(6)')
|
2017-09-19 14:47:10 +00:00
|
|
|
.text()
|
|
|
|
.trim(),
|
2017-10-19 17:43:33 +00:00
|
|
|
Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed,
|
2017-09-19 14:47:10 +00:00
|
|
|
'CPU %'
|
|
|
|
);
|
|
|
|
|
2017-10-17 01:47:25 +00:00
|
|
|
assert.equal(
|
2017-10-18 19:29:33 +00:00
|
|
|
allocationRow.find('td:eq(6) .tooltip').attr('aria-label'),
|
2017-10-17 01:47:25 +00:00
|
|
|
`${Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks)} / ${cpuUsed} MHz`,
|
|
|
|
'Detailed CPU information is in a tooltip'
|
|
|
|
);
|
|
|
|
|
2017-09-19 14:47:10 +00:00
|
|
|
assert.equal(
|
|
|
|
allocationRow
|
2017-10-18 19:29:33 +00:00
|
|
|
.find('td:eq(7)')
|
2017-09-19 14:47:10 +00:00
|
|
|
.text()
|
|
|
|
.trim(),
|
2017-10-17 01:47:25 +00:00
|
|
|
allocStats.resourceUsage.MemoryStats.RSS / 1024 / 1024 / memoryUsed,
|
2017-09-19 14:47:10 +00:00
|
|
|
'Memory used'
|
|
|
|
);
|
|
|
|
|
2017-10-17 01:47:25 +00:00
|
|
|
assert.equal(
|
2017-10-18 19:29:33 +00:00
|
|
|
allocationRow.find('td:eq(7) .tooltip').attr('aria-label'),
|
2017-10-17 01:47:25 +00:00
|
|
|
`${formatBytes([allocStats.resourceUsage.MemoryStats.RSS])} / ${memoryUsed} MiB`,
|
|
|
|
'Detailed memory information is in a tooltip'
|
|
|
|
);
|
|
|
|
|
2017-09-19 14:47:10 +00:00
|
|
|
const node = server.db.nodes.find(allocation.nodeId);
|
|
|
|
const nodeStatsUrl = `//${node.httpAddr}/v1/client/allocation/${allocation.id}/stats`;
|
|
|
|
|
|
|
|
assert.ok(
|
|
|
|
server.pretender.handledRequests.some(req => req.url === nodeStatsUrl),
|
|
|
|
`Requests ${nodeStatsUrl}`
|
|
|
|
);
|
|
|
|
});
|
2017-10-02 19:44:07 +00:00
|
|
|
|
|
|
|
test('when the allocation search has no matches, there is an empty message', function(assert) {
|
|
|
|
fillIn('.search-box input', 'zzzzzz');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.ok(find('.allocations .empty-message'));
|
|
|
|
assert.equal(find('.allocations .empty-message-headline').textContent, 'No Matches');
|
|
|
|
});
|
|
|
|
});
|