github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/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'), [
    36        'dc1',
    37        'dc2',
    38      ]);
    39      assert.deepEqual(topoViz.topology.datacenters[0].nodes.mapBy('node'), [
    40        nodes[0],
    41        nodes[2],
    42      ]);
    43      assert.deepEqual(topoViz.topology.datacenters[1].nodes.mapBy('node'), [
    44        nodes[1],
    45      ]);
    46      assert.deepEqual(
    47        topoViz.topology.datacenters[0].nodes[0].allocations.mapBy('allocation'),
    48        node0Allocs
    49      );
    50      assert.deepEqual(
    51        topoViz.topology.datacenters[1].nodes[0].allocations.mapBy('allocation'),
    52        node1Allocs
    53      );
    54      assert.deepEqual(
    55        topoViz.topology.datacenters[0].nodes[1].allocations.mapBy('allocation'),
    56        node2Allocs
    57      );
    58    });
    59  
    60    test('the topology object contains an allocation index keyed by jobId+taskGroupName', async function (assert) {
    61      assert.expect(7);
    62  
    63      const allocations = [
    64        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'one' }),
    65        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'one' }),
    66        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'two' }),
    67        alloc({ nodeId: 'node0', jobId: 'job1', taskGroupName: 'one' }),
    68        alloc({ nodeId: 'node0', jobId: 'job1', taskGroupName: 'two' }),
    69        alloc({ nodeId: 'node0', jobId: 'job1', taskGroupName: 'three' }),
    70        alloc({ nodeId: 'node0', jobId: 'job2', taskGroupName: 'one' }),
    71        alloc({ nodeId: 'node0', jobId: 'job2', taskGroupName: 'one' }),
    72        alloc({ nodeId: 'node0', jobId: 'job2', taskGroupName: 'one' }),
    73        alloc({ nodeId: 'node0', jobId: 'job2', taskGroupName: 'one' }),
    74      ];
    75  
    76      const nodes = [{ datacenter: 'dc1', id: 'node0', resources: {} }];
    77      const topoViz = this.createComponent({ nodes, allocations });
    78  
    79      topoViz.buildTopology();
    80  
    81      assert.deepEqual(
    82        Object.keys(topoViz.topology.allocationIndex).sort(),
    83        [
    84          JSON.stringify(['job0', 'one']),
    85          JSON.stringify(['job0', 'two']),
    86  
    87          JSON.stringify(['job1', 'one']),
    88          JSON.stringify(['job1', 'two']),
    89          JSON.stringify(['job1', 'three']),
    90  
    91          JSON.stringify(['job2', 'one']),
    92        ].sort()
    93      );
    94  
    95      Object.keys(topoViz.topology.allocationIndex).forEach((key) => {
    96        const [jobId, group] = JSON.parse(key);
    97        assert.deepEqual(
    98          topoViz.topology.allocationIndex[key].mapBy('allocation'),
    99          allocations.filter(
   100            (alloc) => alloc.jobId === jobId && alloc.taskGroupName === group
   101          )
   102        );
   103      });
   104    });
   105  
   106    test('isSingleColumn is true when there is only one datacenter', async function (assert) {
   107      const oneDc = [{ datacenter: 'dc1', id: 'node0', resources: {} }];
   108      const twoDc = [...oneDc, { datacenter: 'dc2', id: 'node1', resources: {} }];
   109  
   110      const topoViz1 = this.createComponent({ nodes: oneDc, allocations: [] });
   111      const topoViz2 = this.createComponent({ nodes: twoDc, allocations: [] });
   112  
   113      topoViz1.buildTopology();
   114      topoViz2.buildTopology();
   115  
   116      assert.ok(topoViz1.isSingleColumn);
   117      assert.notOk(topoViz2.isSingleColumn);
   118    });
   119  
   120    test('isSingleColumn is true when there are multiple datacenters with a high variance in node count', async function (assert) {
   121      const uniformDcs = [
   122        { datacenter: 'dc1', id: 'node0', resources: {} },
   123        { datacenter: 'dc2', id: 'node1', resources: {} },
   124      ];
   125      const skewedDcs = [
   126        { datacenter: 'dc1', id: 'node0', resources: {} },
   127        { datacenter: 'dc2', id: 'node1', resources: {} },
   128        { datacenter: 'dc2', id: 'node2', resources: {} },
   129        { datacenter: 'dc2', id: 'node3', resources: {} },
   130        { datacenter: 'dc2', id: 'node4', resources: {} },
   131      ];
   132  
   133      const twoColumnViz = this.createComponent({
   134        nodes: uniformDcs,
   135        allocations: [],
   136      });
   137      const oneColumViz = this.createComponent({
   138        nodes: skewedDcs,
   139        allocations: [],
   140      });
   141  
   142      twoColumnViz.buildTopology();
   143      oneColumViz.buildTopology();
   144  
   145      assert.notOk(twoColumnViz.isSingleColumn);
   146      assert.ok(oneColumViz.isSingleColumn);
   147    });
   148  
   149    test('datacenterIsSingleColumn is only ever false when isSingleColumn is false and the total node count is high', async function (assert) {
   150      const manyUniformNodes = Array(25)
   151        .fill(null)
   152        .map((_, index) => ({
   153          datacenter: index > 12 ? 'dc2' : 'dc1',
   154          id: `node${index}`,
   155          resources: {},
   156        }));
   157      const manySkewedNodes = Array(25)
   158        .fill(null)
   159        .map((_, index) => ({
   160          datacenter: index > 5 ? 'dc2' : 'dc1',
   161          id: `node${index}`,
   162          resources: {},
   163        }));
   164  
   165      const oneColumnViz = this.createComponent({
   166        nodes: manyUniformNodes,
   167        allocations: [],
   168      });
   169      const twoColumnViz = this.createComponent({
   170        nodes: manySkewedNodes,
   171        allocations: [],
   172      });
   173  
   174      oneColumnViz.buildTopology();
   175      twoColumnViz.buildTopology();
   176  
   177      assert.ok(oneColumnViz.datacenterIsSingleColumn);
   178      assert.notOk(oneColumnViz.isSingleColumn);
   179  
   180      assert.notOk(twoColumnViz.datacenterIsSingleColumn);
   181      assert.ok(twoColumnViz.isSingleColumn);
   182    });
   183  
   184    test('dataForAllocation correctly calculates proportion of node utilization and group key', async function (assert) {
   185      const nodes = [
   186        { datacenter: 'dc1', id: 'node0', resources: { cpu: 100, memory: 250 } },
   187      ];
   188      const allocations = [
   189        alloc({
   190          nodeId: 'node0',
   191          jobId: 'job0',
   192          taskGroupName: 'group',
   193          allocatedResources: { cpu: 50, memory: 25 },
   194        }),
   195      ];
   196  
   197      const topoViz = this.createComponent({ nodes, allocations });
   198      topoViz.buildTopology();
   199  
   200      assert.equal(
   201        topoViz.topology.datacenters[0].nodes[0].allocations[0].cpuPercent,
   202        0.5
   203      );
   204      assert.equal(
   205        topoViz.topology.datacenters[0].nodes[0].allocations[0].memoryPercent,
   206        0.1
   207      );
   208    });
   209  
   210    test('allocations that reference nonexistent nodes are ignored', async function (assert) {
   211      const nodes = [{ datacenter: 'dc1', id: 'node0', resources: {} }];
   212  
   213      const allocations = [
   214        alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'group' }),
   215        alloc({ nodeId: 'node404', jobId: 'job1', taskGroupName: 'group' }),
   216      ];
   217  
   218      const topoViz = this.createComponent({ nodes, allocations });
   219  
   220      topoViz.buildTopology();
   221  
   222      assert.deepEqual(topoViz.topology.datacenters[0].nodes.mapBy('node'), [
   223        nodes[0],
   224      ]);
   225      assert.deepEqual(
   226        topoViz.topology.datacenters[0].nodes[0].allocations.mapBy('allocation'),
   227        [allocations[0]]
   228      );
   229    });
   230  });
   231  
   232  function alloc(props) {
   233    return {
   234      ...props,
   235      allocatedResources: props.allocatedResources || {},
   236      belongsTo(type) {
   237        return {
   238          id() {
   239            return type === 'job' ? props.jobId : props.nodeId;
   240          },
   241        };
   242      },
   243    };
   244  }