Skip to content

Commit 4d5fef6

Browse files
Filter out nodes that don't have NodeResources from the topo viz
1 parent 789225d commit 4d5fef6

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

ui/app/components/topo-viz.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,18 @@ export default class TopoViz extends Component {
8383
const nodes = this.args.nodes;
8484
const allocations = this.args.allocations;
8585

86+
// Nodes may not have a resources property due to having an old Nomad agent version.
87+
const badNodes = [];
88+
8689
// Wrap nodes in a topo viz specific data structure and build an index to speed up allocation assignment
8790
const nodeContainers = [];
8891
const nodeIndex = {};
8992
nodes.forEach(node => {
93+
if (!node.resources) {
94+
badNodes.push(node);
95+
return;
96+
}
97+
9098
const container = this.dataForNode(node);
9199
nodeContainers.push(container);
92100
nodeIndex[node.id] = container;
@@ -99,7 +107,7 @@ export default class TopoViz extends Component {
99107
const nodeId = allocation.belongsTo('node').id();
100108
const nodeContainer = nodeIndex[nodeId];
101109

102-
// Ignore orphaned allocations
110+
// Ignore orphaned allocations and allocations on nodes with an old Nomad agent version.
103111
if (!nodeContainer) return;
104112

105113
const allocationContainer = this.dataForAllocation(allocation, nodeContainer);
@@ -131,6 +139,15 @@ export default class TopoViz extends Component {
131139
.domain(extent(nodeContainers.mapBy('memory'))),
132140
};
133141
this.topology = topology;
142+
143+
if (badNodes.length && this.args.onDataError) {
144+
this.args.onDataError([
145+
{
146+
type: 'filtered-nodes',
147+
context: badNodes,
148+
},
149+
]);
150+
}
134151
}
135152

136153
@action

ui/tests/integration/components/topo-viz-test.js

+33-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ module('Integration | Component | TopoViz', function(hooks) {
3939
@nodes={{this.nodes}}
4040
@allocations={{this.allocations}}
4141
@onAllocationSelect={{this.onAllocationSelect}}
42-
@onNodeSelect={{this.onNodeSelect}} />
42+
@onNodeSelect={{this.onNodeSelect}}
43+
@onDataError={{this.onDataError}} />
4344
`;
4445

4546
test('presents as a FlexMasonry of datacenters', async function(assert) {
@@ -167,4 +168,35 @@ module('Integration | Component | TopoViz', function(hooks) {
167168
await TopoViz.datacenters[0].nodes[0].memoryRects[0].select();
168169
assert.equal(TopoViz.allocationAssociations.length, 0);
169170
});
171+
172+
test('when one or more nodes are missing the resources property, those nodes are filtered out of the topology view and onDataError is called', async function(assert) {
173+
const badNode = node('dc1', 'node0', 1000, 500);
174+
delete badNode.resources;
175+
176+
this.setProperties({
177+
nodes: [badNode, node('dc1', 'node1', 1000, 500)],
178+
allocations: [
179+
alloc('node0', 'job1', 'group', 100, 100),
180+
alloc('node0', 'job1', 'group', 100, 100),
181+
alloc('node1', 'job1', 'group', 100, 100),
182+
alloc('node1', 'job1', 'group', 100, 100),
183+
alloc('node0', 'job1', 'groupTwo', 100, 100),
184+
],
185+
onNodeSelect: sinon.spy(),
186+
onAllocationSelect: sinon.spy(),
187+
onDataError: sinon.spy(),
188+
});
189+
190+
await this.render(commonTemplate);
191+
192+
assert.ok(this.onDataError.calledOnce);
193+
assert.deepEqual(this.onDataError.getCall(0).args[0], [
194+
{
195+
type: 'filtered-nodes',
196+
context: [this.nodes[0]],
197+
},
198+
]);
199+
200+
assert.equal(TopoViz.datacenters[0].nodes.length, 1);
201+
});
170202
});

0 commit comments

Comments
 (0)