diff --git a/ui/app/services/system.js b/ui/app/services/system.js
index 8af8aa33a..cd296f338 100644
--- a/ui/app/services/system.js
+++ b/ui/app/services/system.js
@@ -39,7 +39,12 @@ export default class SystemService extends Service {
.authorizedRawRequest(`/${namespace}/agent/self`)
.then(jsonWithDefault({}))
.then(agent => {
- agent.version = agent.member?.Tags?.build || 'Unknown';
+ if (agent?.config?.Version) {
+ const { Version, VersionPrerelease, VersionMetadata } = agent.config.Version;
+ agent.version = Version;
+ if (VersionPrerelease) agent.version = `${agent.version}-${VersionPrerelease}`;
+ if (VersionMetadata) agent.version = `${agent.version}+${VersionMetadata}`;
+ }
return agent;
}),
});
diff --git a/ui/app/templates/components/gutter-menu.hbs b/ui/app/templates/components/gutter-menu.hbs
index d23993a18..f2ef4048f 100644
--- a/ui/app/templates/components/gutter-menu.hbs
+++ b/ui/app/templates/components/gutter-menu.hbs
@@ -68,9 +68,11 @@
Topology
+ {{#if this.system.agent.version}}
+ {{/if}}
diff --git a/ui/mirage/config.js b/ui/mirage/config.js
index 267d5ac50..7cfa6950f 100644
--- a/ui/mirage/config.js
+++ b/ui/mirage/config.js
@@ -9,7 +9,7 @@ import formatHost from 'nomad-ui/utils/format-host';
export function findLeader(schema) {
const agent = schema.agents.first();
- return formatHost(agent.address, agent.tags.port);
+ return formatHost(agent.member.Address, agent.member.Tags.port);
}
export function filesForPath(allocFiles, filterPath) {
@@ -335,14 +335,12 @@ export default function() {
const firstRegion = regions.first();
return {
ServerRegion: firstRegion ? firstRegion.id : null,
- Members: this.serialize(agents.all()),
+ Members: this.serialize(agents.all()).map(({ member }) => ({ ...member })),
};
});
this.get('/agent/self', function({ agents }) {
- return {
- member: this.serialize(agents.first()),
- };
+ return agents.first();
});
this.get('/agent/monitor', function({ agents, nodes }, { queryParams }) {
@@ -579,7 +577,10 @@ export default function() {
});
});
- this.post('/search/fuzzy', function( { allocations, jobs, nodes, taskGroups, csiPlugins }, { requestBody }) {
+ this.post('/search/fuzzy', function(
+ { allocations, jobs, nodes, taskGroups, csiPlugins },
+ { requestBody }
+ ) {
const { Text } = JSON.parse(requestBody);
const matchedAllocs = allocations.where(allocation => allocation.name.includes(Text));
@@ -590,33 +591,22 @@ export default function() {
const transformedAllocs = matchedAllocs.models.map(alloc => ({
ID: alloc.name,
- Scope: [
- (alloc.namespace || {}).id,
- alloc.id,
- ],
+ Scope: [(alloc.namespace || {}).id, alloc.id],
}));
const transformedGroups = matchedGroups.models.map(group => ({
ID: group.name,
- Scope: [
- group.job.namespace,
- group.job.id,
- ],
+ Scope: [group.job.namespace, group.job.id],
}));
const transformedJobs = matchedJobs.models.map(job => ({
ID: job.name,
- Scope: [
- job.namespace,
- job.id,
- ]
+ Scope: [job.namespace, job.id],
}));
const transformedNodes = matchedNodes.models.map(node => ({
ID: node.name,
- Scope: [
- node.id,
- ],
+ Scope: [node.id],
}));
const transformedPlugins = matchedPlugins.models.map(plugin => ({
@@ -644,7 +634,7 @@ export default function() {
nodes: truncatedNodes.length < transformedNodes.length,
plugins: truncatedPlugins.length < transformedPlugins.length,
},
- }
+ };
});
this.get('/recommendations', function(
diff --git a/ui/mirage/factories/agent.js b/ui/mirage/factories/agent.js
index 26fcc5b00..cf985d95b 100644
--- a/ui/mirage/factories/agent.js
+++ b/ui/mirage/factories/agent.js
@@ -8,20 +8,41 @@ const AGENT_STATUSES = ['alive', 'leaving', 'left', 'failed'];
export default Factory.extend({
id: i => (i / 100 >= 1 ? `${UUIDS[i]}-${i}` : UUIDS[i]),
- name: () => `nomad@${faker.random.boolean() ? faker.internet.ip() : faker.internet.ipv6()}`,
- status: () => faker.helpers.randomize(AGENT_STATUSES),
- serfPort: () => faker.random.number({ min: 4000, max: 4999 }),
+ name: () => generateName(),
- address() {
- return this.name.split('@')[1];
+ config: {
+ Version: {
+ Version: '1.1.0',
+ VersionMetadata: 'ent',
+ VersionPrerelease: 'dev',
+ },
},
- tags() {
- const rpcPortCandidate = faker.random.number({ min: 4000, max: 4999 });
+ member() {
+ const serfPort = faker.random.number({ min: 4000, max: 4999 });
return {
- port: rpcPortCandidate === this.serfPort ? rpcPortCandidate + 1 : rpcPortCandidate,
- dc: faker.helpers.randomize(DATACENTERS),
+ Name: this.name,
+ Port: serfPort,
+ Status: faker.helpers.randomize(AGENT_STATUSES),
+ Address: generateAddress(this.name),
+ Tags: generateTags(serfPort),
};
},
});
+
+function generateName() {
+ return `nomad@${faker.random.boolean() ? faker.internet.ip() : faker.internet.ipv6()}`;
+}
+
+function generateAddress(name) {
+ return name.split('@')[1];
+}
+
+function generateTags(serfPort) {
+ const rpcPortCandidate = faker.random.number({ min: 4000, max: 4999 });
+ return {
+ port: rpcPortCandidate === serfPort ? rpcPortCandidate + 1 : rpcPortCandidate,
+ dc: faker.helpers.randomize(DATACENTERS),
+ };
+}
diff --git a/ui/mirage/serializers/agent.js b/ui/mirage/serializers/agent.js
new file mode 100644
index 000000000..13abd2b12
--- /dev/null
+++ b/ui/mirage/serializers/agent.js
@@ -0,0 +1,10 @@
+import ApplicationSerializer from './application';
+
+export default ApplicationSerializer.extend({
+ keyForAttribute(str) {
+ if (str === 'config' || str === 'member') {
+ return str;
+ }
+ return ApplicationSerializer.prototype.keyForAttribute.apply(this, arguments);
+ },
+});
diff --git a/ui/tests/acceptance/server-detail-test.js b/ui/tests/acceptance/server-detail-test.js
index 177b1bff4..507d83fb8 100644
--- a/ui/tests/acceptance/server-detail-test.js
+++ b/ui/tests/acceptance/server-detail-test.js
@@ -33,14 +33,16 @@ module('Acceptance | server detail', function(hooks) {
});
test('the details ribbon displays basic information about the server', async function(assert) {
- assert.ok(ServerDetail.serverStatus.includes(agent.status));
- assert.ok(ServerDetail.address.includes(formatHost(agent.address, agent.tags.port)));
- assert.ok(ServerDetail.datacenter.includes(agent.tags.dc));
+ assert.ok(ServerDetail.serverStatus.includes(agent.member.Status));
+ assert.ok(
+ ServerDetail.address.includes(formatHost(agent.member.Address, agent.member.Tags.port))
+ );
+ assert.ok(ServerDetail.datacenter.includes(agent.member.Tags.dc));
});
test('the server detail page should list all tags for the server', async function(assert) {
- const tags = Object.keys(agent.tags)
- .map(name => ({ name, value: agent.tags[name] }))
+ const tags = Object.keys(agent.member.Tags)
+ .map(name => ({ name, value: agent.member.Tags[name] }))
.sortBy('name');
assert.equal(ServerDetail.tags.length, tags.length, '# of tags');
diff --git a/ui/tests/acceptance/servers-list-test.js b/ui/tests/acceptance/servers-list-test.js
index 1faded1e4..d4b30c580 100644
--- a/ui/tests/acceptance/servers-list-test.js
+++ b/ui/tests/acceptance/servers-list-test.js
@@ -13,9 +13,9 @@ const minimumSetup = () => {
};
const agentSort = leader => (a, b) => {
- if (formatHost(a.address, a.tags.port) === leader) {
+ if (formatHost(a.member.Address, a.member.Tags.port) === leader) {
return 1;
- } else if (formatHost(b.address, b.tags.port) === leader) {
+ } else if (formatHost(b.member.Address, b.member.Tags.port) === leader) {
return -1;
}
return 0;
@@ -58,11 +58,11 @@ module('Acceptance | servers list', function(hooks) {
const agentRow = ServersList.servers.objectAt(0);
assert.equal(agentRow.name, agent.name, 'Name');
- assert.equal(agentRow.status, agent.status, 'Status');
+ assert.equal(agentRow.status, agent.member.Status, 'Status');
assert.equal(agentRow.leader, 'True', 'Leader?');
- assert.equal(agentRow.address, agent.address, 'Address');
- assert.equal(agentRow.serfPort, agent.serfPort, 'Serf Port');
- assert.equal(agentRow.datacenter, agent.tags.dc, 'Datacenter');
+ assert.equal(agentRow.address, agent.member.Address, 'Address');
+ assert.equal(agentRow.serfPort, agent.member.Port, 'Serf Port');
+ assert.equal(agentRow.datacenter, agent.member.Tags.dc, 'Datacenter');
});
test('each server should link to the server detail page', async function(assert) {