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  });