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) {