github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/acceptance/topology-test.js (about) 1 import { get } from '@ember/object'; 2 import { currentURL } from '@ember/test-helpers'; 3 import { module, test } from 'qunit'; 4 import { setupApplicationTest } from 'ember-qunit'; 5 import { setupMirage } from 'ember-cli-mirage/test-support'; 6 import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit'; 7 import Topology from 'nomad-ui/tests/pages/topology'; 8 import { reduceToLargestUnit } from 'nomad-ui/helpers/format-bytes'; 9 import queryString from 'query-string'; 10 11 const sumResources = (list, dimension) => 12 list.reduce((agg, val) => agg + (get(val, dimension) || 0), 0); 13 14 module('Acceptance | topology', function(hooks) { 15 setupApplicationTest(hooks); 16 setupMirage(hooks); 17 18 hooks.beforeEach(function() { 19 server.create('job', { createAllocations: false }); 20 }); 21 22 test('it passes an accessibility audit', async function(assert) { 23 server.createList('node', 3); 24 server.createList('allocation', 5); 25 26 await Topology.visit(); 27 await a11yAudit(assert); 28 }); 29 30 test('by default the info panel shows cluster aggregate stats', async function(assert) { 31 server.createList('node', 3); 32 server.createList('allocation', 5); 33 34 await Topology.visit(); 35 assert.equal(Topology.infoPanelTitle, 'Cluster Details'); 36 assert.notOk(Topology.filteredNodesWarning.isPresent); 37 38 assert.equal( 39 Topology.clusterInfoPanel.nodeCount, 40 `${server.schema.nodes.all().length} Clients` 41 ); 42 43 const allocs = server.schema.allocations.all().models; 44 const scheduledAllocs = allocs.filter(alloc => 45 ['pending', 'running'].includes(alloc.clientStatus) 46 ); 47 assert.equal(Topology.clusterInfoPanel.allocCount, `${scheduledAllocs.length} Allocations`); 48 49 const nodeResources = server.schema.nodes.all().models.mapBy('nodeResources'); 50 const taskResources = scheduledAllocs 51 .mapBy('taskResources.models') 52 .flat() 53 .mapBy('resources'); 54 55 const totalMem = sumResources(nodeResources, 'Memory.MemoryMB'); 56 const totalCPU = sumResources(nodeResources, 'Cpu.CpuShares'); 57 const reservedMem = sumResources(taskResources, 'Memory.MemoryMB'); 58 const reservedCPU = sumResources(taskResources, 'Cpu.CpuShares'); 59 60 assert.equal(Topology.clusterInfoPanel.memoryProgressValue, reservedMem / totalMem); 61 assert.equal(Topology.clusterInfoPanel.cpuProgressValue, reservedCPU / totalCPU); 62 63 const [rNum, rUnit] = reduceToLargestUnit(reservedMem * 1024 * 1024); 64 const [tNum, tUnit] = reduceToLargestUnit(totalMem * 1024 * 1024); 65 66 assert.equal( 67 Topology.clusterInfoPanel.memoryAbsoluteValue, 68 `${Math.floor(rNum)} ${rUnit} / ${Math.floor(tNum)} ${tUnit} reserved` 69 ); 70 71 assert.equal( 72 Topology.clusterInfoPanel.cpuAbsoluteValue, 73 `${reservedCPU} MHz / ${totalCPU} MHz reserved` 74 ); 75 }); 76 77 test('all allocations for all namespaces and all clients are queried on load', async function(assert) { 78 server.createList('node', 3); 79 server.createList('allocation', 5); 80 81 await Topology.visit(); 82 const requests = this.server.pretender.handledRequests; 83 assert.ok(requests.findBy('url', '/v1/nodes?resources=true')); 84 85 const allocationsRequest = requests.find(req => req.url.startsWith('/v1/allocations')); 86 assert.ok(allocationsRequest); 87 88 const allocationRequestParams = queryString.parse(allocationsRequest.url.split('?')[1]); 89 assert.deepEqual(allocationRequestParams, { 90 namespace: '*', 91 task_states: 'false', 92 resources: 'true', 93 }); 94 }); 95 96 test('when an allocation is selected, the info panel shows information on the allocation', async function(assert) { 97 const nodes = server.createList('node', 5); 98 const job = server.create('job', { createAllocations: false }); 99 const taskGroup = server.schema.find('taskGroup', job.taskGroupIds[0]).name; 100 const allocs = server.createList('allocation', 5, { 101 forceRunningClientStatus: true, 102 jobId: job.id, 103 taskGroup, 104 }); 105 106 // Get the first alloc of the first node that has an alloc 107 const sortedNodes = nodes.sortBy('datacenter'); 108 let node, alloc; 109 for (let n of sortedNodes) { 110 alloc = allocs.find(a => a.nodeId === n.id); 111 if (alloc) { 112 node = n; 113 break; 114 } 115 } 116 117 const dcIndex = nodes 118 .mapBy('datacenter') 119 .uniq() 120 .sort() 121 .indexOf(node.datacenter); 122 const nodeIndex = nodes.filterBy('datacenter', node.datacenter).indexOf(node); 123 124 const reset = async () => { 125 await Topology.visit(); 126 await Topology.viz.datacenters[dcIndex].nodes[nodeIndex].memoryRects[0].select(); 127 }; 128 129 await reset(); 130 assert.equal(Topology.infoPanelTitle, 'Allocation Details'); 131 132 assert.equal(Topology.allocInfoPanel.id, alloc.id.split('-')[0]); 133 134 const uniqueClients = allocs.mapBy('nodeId').uniq(); 135 assert.equal(Topology.allocInfoPanel.siblingAllocs, `Sibling Allocations: ${allocs.length}`); 136 assert.equal( 137 Topology.allocInfoPanel.uniquePlacements, 138 `Unique Client Placements: ${uniqueClients.length}` 139 ); 140 141 assert.equal(Topology.allocInfoPanel.job, job.name); 142 assert.ok(Topology.allocInfoPanel.taskGroup.endsWith(alloc.taskGroup)); 143 assert.equal(Topology.allocInfoPanel.client, node.id.split('-')[0]); 144 145 await Topology.allocInfoPanel.visitAlloc(); 146 assert.equal(currentURL(), `/allocations/${alloc.id}`); 147 148 await reset(); 149 150 await Topology.allocInfoPanel.visitJob(); 151 assert.equal(currentURL(), `/jobs/${job.id}`); 152 153 await reset(); 154 155 await Topology.allocInfoPanel.visitClient(); 156 assert.equal(currentURL(), `/clients/${node.id}`); 157 }); 158 159 test('when a node is selected, the info panel shows information on the node', async function(assert) { 160 // A high node count is required for node selection 161 const nodes = server.createList('node', 51); 162 const node = nodes.sortBy('datacenter')[0]; 163 server.createList('allocation', 5, { forceRunningClientStatus: true }); 164 165 const allocs = server.schema.allocations.where({ nodeId: node.id }).models; 166 167 await Topology.visit(); 168 169 await Topology.viz.datacenters[0].nodes[0].selectNode(); 170 assert.equal(Topology.infoPanelTitle, 'Client Details'); 171 172 assert.equal(Topology.nodeInfoPanel.id, node.id.split('-')[0]); 173 assert.equal(Topology.nodeInfoPanel.name, `Name: ${node.name}`); 174 assert.equal(Topology.nodeInfoPanel.address, `Address: ${node.httpAddr}`); 175 assert.equal(Topology.nodeInfoPanel.status, `Status: ${node.status}`); 176 177 assert.equal(Topology.nodeInfoPanel.drainingLabel, node.drain ? 'Yes' : 'No'); 178 assert.equal( 179 Topology.nodeInfoPanel.eligibleLabel, 180 node.schedulingEligibility === 'eligible' ? 'Yes' : 'No' 181 ); 182 183 assert.equal(Topology.nodeInfoPanel.drainingIsAccented, node.drain); 184 assert.equal( 185 Topology.nodeInfoPanel.eligibleIsAccented, 186 node.schedulingEligibility !== 'eligible' 187 ); 188 189 const taskResources = allocs 190 .mapBy('taskResources.models') 191 .flat() 192 .mapBy('resources'); 193 const reservedMem = sumResources(taskResources, 'Memory.MemoryMB'); 194 const reservedCPU = sumResources(taskResources, 'Cpu.CpuShares'); 195 196 const totalMem = node.nodeResources.Memory.MemoryMB; 197 const totalCPU = node.nodeResources.Cpu.CpuShares; 198 199 assert.equal(Topology.nodeInfoPanel.memoryProgressValue, reservedMem / totalMem); 200 assert.equal(Topology.nodeInfoPanel.cpuProgressValue, reservedCPU / totalCPU); 201 202 const [rNum, rUnit] = reduceToLargestUnit(reservedMem * 1024 * 1024); 203 const [tNum, tUnit] = reduceToLargestUnit(totalMem * 1024 * 1024); 204 205 assert.equal( 206 Topology.nodeInfoPanel.memoryAbsoluteValue, 207 `${Math.floor(rNum)} ${rUnit} / ${Math.floor(tNum)} ${tUnit} reserved` 208 ); 209 210 assert.equal( 211 Topology.nodeInfoPanel.cpuAbsoluteValue, 212 `${reservedCPU} MHz / ${totalCPU} MHz reserved` 213 ); 214 215 await Topology.nodeInfoPanel.visitNode(); 216 assert.equal(currentURL(), `/clients/${node.id}`); 217 }); 218 219 test('when one or more nodes lack the NodeResources property, a warning message is shown', async function(assert) { 220 server.createList('node', 3); 221 server.createList('allocation', 5); 222 223 server.schema.nodes.all().models[0].update({ nodeResources: null }); 224 225 await Topology.visit(); 226 assert.ok(Topology.filteredNodesWarning.isPresent); 227 assert.ok(Topology.filteredNodesWarning.message.startsWith('1')); 228 }); 229 });