diff --git a/ui/app/components/topo-viz.js b/ui/app/components/topo-viz.js
index 18a9c3735..d1254a0dc 100644
--- a/ui/app/components/topo-viz.js
+++ b/ui/app/components/topo-viz.js
@@ -83,10 +83,18 @@ export default class TopoViz extends Component {
const nodes = this.args.nodes;
const allocations = this.args.allocations;
+ // Nodes may not have a resources property due to having an old Nomad agent version.
+ const badNodes = [];
+
// Wrap nodes in a topo viz specific data structure and build an index to speed up allocation assignment
const nodeContainers = [];
const nodeIndex = {};
nodes.forEach(node => {
+ if (!node.resources) {
+ badNodes.push(node);
+ return;
+ }
+
const container = this.dataForNode(node);
nodeContainers.push(container);
nodeIndex[node.id] = container;
@@ -99,7 +107,7 @@ export default class TopoViz extends Component {
const nodeId = allocation.belongsTo('node').id();
const nodeContainer = nodeIndex[nodeId];
- // Ignore orphaned allocations
+ // Ignore orphaned allocations and allocations on nodes with an old Nomad agent version.
if (!nodeContainer) return;
const allocationContainer = this.dataForAllocation(allocation, nodeContainer);
@@ -131,6 +139,15 @@ export default class TopoViz extends Component {
.domain(extent(nodeContainers.mapBy('memory'))),
};
this.topology = topology;
+
+ if (badNodes.length && this.args.onDataError) {
+ this.args.onDataError([
+ {
+ type: 'filtered-nodes',
+ context: badNodes,
+ },
+ ]);
+ }
}
@action
diff --git a/ui/app/controllers/topology.js b/ui/app/controllers/topology.js
index 9b4d98fdf..9bb0bec43 100644
--- a/ui/app/controllers/topology.js
+++ b/ui/app/controllers/topology.js
@@ -2,6 +2,7 @@ import Controller from '@ember/controller';
import { computed, action } from '@ember/object';
import { alias } from '@ember/object/computed';
import { inject as service } from '@ember/service';
+import { tracked } from '@glimmer/tracking';
import classic from 'ember-classic-decorator';
import { reduceToLargestUnit } from 'nomad-ui/helpers/format-bytes';
@@ -13,6 +14,8 @@ export default class TopologyControllers extends Controller {
@alias('userSettings.showTopoVizPollingNotice') showPollingNotice;
+ @tracked filteredNodes = null;
+
@computed('model.nodes.@each.datacenter')
get datacenters() {
return Array.from(new Set(this.model.nodes.mapBy('datacenter'))).compact();
@@ -117,4 +120,12 @@ export default class TopologyControllers extends Controller {
setNode(node) {
this.set('activeNode', node);
}
+
+ @action
+ handleTopoVizDataError(errors) {
+ const filteredNodesError = errors.findBy('type', 'filtered-nodes');
+ if (filteredNodesError) {
+ this.filteredNodes = filteredNodesError.context;
+ }
+ }
}
diff --git a/ui/app/templates/topology.hbs b/ui/app/templates/topology.hbs
index e88731d8d..c41b1de9c 100644
--- a/ui/app/templates/topology.hbs
+++ b/ui/app/templates/topology.hbs
@@ -4,6 +4,19 @@
{{#if this.isForbidden}}
{{else}}
+ {{#if this.filteredNodes}}
+
+
+
+
Some Clients Were Filtered
+
{{this.filteredNodes.length}} {{if (eq this.filteredNodes.length 1) "client was" "clients were"}} filtered from the topology visualization. This is most likely due to the {{pluralize "client" this.filteredNodes.length}} running a version of Nomad <0.9.0.