github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/unit/components/topo-viz-test.js (about)

     1  import { module, test } from 'qunit';
     2  import { setupTest } from 'ember-qunit';
     3  import setupGlimmerComponentFactory from 'nomad-ui/tests/helpers/glimmer-factory';
     4  
     5  module('Unit | Component | TopoViz', function(hooks) {
     6    setupTest(hooks);
     7    setupGlimmerComponentFactory(hooks, 'topo-viz');
     8  
     9    test('the topology object properly organizes a tree of datacenters > nodes > allocations', async function(assert) {
    10      const nodes = [
    11        { datacenter: 'dc1', id: 'node0', resources: {} },
    12        { datacenter: 'dc2', id: 'node1', resources: {} },
    13        { datacenter: 'dc1', id: 'node2', resources: {} },
    14      ];
    15  
    16      const node0Allocs = [
    17        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'group' }),
    18        alloc({ nodeId: 'node0', jobId: 'job1', taskGroupName: 'group' }),
    19      ];
    20      const node1Allocs = [
    21        alloc({ nodeId: 'node1', jobId: 'job0', taskGroupName: 'group' }),
    22        alloc({ nodeId: 'node1', jobId: 'job1', taskGroupName: 'group' }),
    23      ];
    24      const node2Allocs = [
    25        alloc({ nodeId: 'node2', jobId: 'job0', taskGroupName: 'group' }),
    26        alloc({ nodeId: 'node2', jobId: 'job1', taskGroupName: 'group' }),
    27      ];
    28  
    29      const allocations = [...node0Allocs, ...node1Allocs, ...node2Allocs];
    30  
    31      const topoViz = this.createComponent({ nodes, allocations });
    32  
    33      topoViz.buildTopology();
    34  
    35      assert.deepEqual(topoViz.topology.datacenters.mapBy('name'), ['dc1', 'dc2']);
    36      assert.deepEqual(topoViz.topology.datacenters[0].nodes.mapBy('node'), [nodes[0], nodes[2]]);
    37      assert.deepEqual(topoViz.topology.datacenters[1].nodes.mapBy('node'), [nodes[1]]);
    38      assert.deepEqual(
    39        topoViz.topology.datacenters[0].nodes[0].allocations.mapBy('allocation'),
    40        node0Allocs
    41      );
    42      assert.deepEqual(
    43        topoViz.topology.datacenters[1].nodes[0].allocations.mapBy('allocation'),
    44        node1Allocs
    45      );
    46      assert.deepEqual(
    47        topoViz.topology.datacenters[0].nodes[1].allocations.mapBy('allocation'),
    48        node2Allocs
    49      );
    50    });
    51  
    52    test('the topology object contains an allocation index keyed by jobId+taskGroupName', async function(assert) {
    53      const allocations = [
    54        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'one' }),
    55        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'one' }),
    56        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'two' }),
    57        alloc({ nodeId: 'node0', jobId: 'job1', taskGroupName: 'one' }),
    58        alloc({ nodeId: 'node0', jobId: 'job1', taskGroupName: 'two' }),
    59        alloc({ nodeId: 'node0', jobId: 'job1', taskGroupName: 'three' }),
    60        alloc({ nodeId: 'node0', jobId: 'job2', taskGroupName: 'one' }),
    61        alloc({ nodeId: 'node0', jobId: 'job2', taskGroupName: 'one' }),
    62        alloc({ nodeId: 'node0', jobId: 'job2', taskGroupName: 'one' }),
    63        alloc({ nodeId: 'node0', jobId: 'job2', taskGroupName: 'one' }),
    64      ];
    65  
    66      const nodes = [{ datacenter: 'dc1', id: 'node0', resources: {} }];
    67      const topoViz = this.createComponent({ nodes, allocations });
    68  
    69      topoViz.buildTopology();
    70  
    71      assert.deepEqual(
    72        Object.keys(topoViz.topology.allocationIndex).sort(),
    73        [
    74          JSON.stringify(['job0', 'one']),
    75          JSON.stringify(['job0', 'two']),
    76  
    77          JSON.stringify(['job1', 'one']),
    78          JSON.stringify(['job1', 'two']),
    79          JSON.stringify(['job1', 'three']),
    80  
    81          JSON.stringify(['job2', 'one']),
    82        ].sort()
    83      );
    84  
    85      Object.keys(topoViz.topology.allocationIndex).forEach(key => {
    86        const [jobId, group] = JSON.parse(key);
    87        assert.deepEqual(
    88          topoViz.topology.allocationIndex[key].mapBy('allocation'),
    89          allocations.filter(alloc => alloc.jobId === jobId && alloc.taskGroupName === group)
    90        );
    91      });
    92    });
    93  
    94    test('isSingleColumn is true when there is only one datacenter', async function(assert) {
    95      const oneDc = [{ datacenter: 'dc1', id: 'node0', resources: {} }];
    96      const twoDc = [...oneDc, { datacenter: 'dc2', id: 'node1', resources: {} }];
    97  
    98      const topoViz1 = this.createComponent({ nodes: oneDc, allocations: [] });
    99      const topoViz2 = this.createComponent({ nodes: twoDc, allocations: [] });
   100  
   101      topoViz1.buildTopology();
   102      topoViz2.buildTopology();
   103  
   104      assert.ok(topoViz1.isSingleColumn);
   105      assert.notOk(topoViz2.isSingleColumn);
   106    });
   107  
   108    test('isSingleColumn is true when there are multiple datacenters with a high variance in node count', async function(assert) {
   109      const uniformDcs = [
   110        { datacenter: 'dc1', id: 'node0', resources: {} },
   111        { datacenter: 'dc2', id: 'node1', resources: {} },
   112      ];
   113      const skewedDcs = [
   114        { datacenter: 'dc1', id: 'node0', resources: {} },
   115        { datacenter: 'dc2', id: 'node1', resources: {} },
   116        { datacenter: 'dc2', id: 'node2', resources: {} },
   117        { datacenter: 'dc2', id: 'node3', resources: {} },
   118        { datacenter: 'dc2', id: 'node4', resources: {} },
   119      ];
   120  
   121      const twoColumnViz = this.createComponent({ nodes: uniformDcs, allocations: [] });
   122      const oneColumViz = this.createComponent({ nodes: skewedDcs, allocations: [] });
   123  
   124      twoColumnViz.buildTopology();
   125      oneColumViz.buildTopology();
   126  
   127      assert.notOk(twoColumnViz.isSingleColumn);
   128      assert.ok(oneColumViz.isSingleColumn);
   129    });
   130  
   131    test('datacenterIsSingleColumn is only ever false when isSingleColumn is false and the total node count is high', async function(assert) {
   132      const manyUniformNodes = Array(25)
   133        .fill(null)
   134        .map((_, index) => ({
   135          datacenter: index > 12 ? 'dc2' : 'dc1',
   136          id: `node${index}`,
   137          resources: {},
   138        }));
   139      const manySkewedNodes = Array(25)
   140        .fill(null)
   141        .map((_, index) => ({
   142          datacenter: index > 5 ? 'dc2' : 'dc1',
   143          id: `node${index}`,
   144          resources: {},
   145        }));
   146  
   147      const oneColumnViz = this.createComponent({ nodes: manyUniformNodes, allocations: [] });
   148      const twoColumnViz = this.createComponent({ nodes: manySkewedNodes, allocations: [] });
   149  
   150      oneColumnViz.buildTopology();
   151      twoColumnViz.buildTopology();
   152  
   153      assert.ok(oneColumnViz.datacenterIsSingleColumn);
   154      assert.notOk(oneColumnViz.isSingleColumn);
   155  
   156      assert.notOk(twoColumnViz.datacenterIsSingleColumn);
   157      assert.ok(twoColumnViz.isSingleColumn);
   158    });
   159  
   160    test('dataForAllocation correctly calculates proportion of node utilization and group key', async function(assert) {
   161      const nodes = [{ datacenter: 'dc1', id: 'node0', resources: { cpu: 100, memory: 250 } }];
   162      const allocations = [
   163        alloc({
   164          nodeId: 'node0',
   165          jobId: 'job0',
   166          taskGroupName: 'group',
   167          allocatedResources: { cpu: 50, memory: 25 },
   168        }),
   169      ];
   170  
   171      const topoViz = this.createComponent({ nodes, allocations });
   172      topoViz.buildTopology();
   173  
   174      assert.equal(topoViz.topology.datacenters[0].nodes[0].allocations[0].cpuPercent, 0.5);
   175      assert.equal(topoViz.topology.datacenters[0].nodes[0].allocations[0].memoryPercent, 0.1);
   176    });
   177  
   178    test('allocations that reference nonexistent nodes are ignored', async function(assert) {
   179      const nodes = [{ datacenter: 'dc1', id: 'node0', resources: {} }];
   180  
   181      const allocations = [
   182        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'group' }),
   183        alloc({ nodeId: 'node404', jobId: 'job1', taskGroupName: 'group' }),
   184      ];
   185  
   186      const topoViz = this.createComponent({ nodes, allocations });
   187  
   188      topoViz.buildTopology();
   189  
   190      assert.deepEqual(topoViz.topology.datacenters[0].nodes.mapBy('node'), [nodes[0]]);
   191      assert.deepEqual(topoViz.topology.datacenters[0].nodes[0].allocations.mapBy('allocation'), [
   192        allocations[0],
   193      ]);
   194    });
   195  });
   196  
   197  function alloc(props) {
   198    return {
   199      ...props,
   200      allocatedResources: props.allocatedResources || {},
   201      belongsTo(type) {
   202        return {
   203          id() {
   204            return type === 'job' ? props.jobId : props.nodeId;
   205          },
   206        };
   207      },
   208    };
   209  }