diff --git a/ui/app/models/node-attributes.js b/ui/app/models/node-attributes.js index c893d8500..232dae160 100644 --- a/ui/app/models/node-attributes.js +++ b/ui/app/models/node-attributes.js @@ -9,8 +9,13 @@ export default Fragment.extend({ attributes: attr(), attributesStructured: computed('attributes', function() { - // `unflatten` doesn't sort keys before unflattening, so manual preprocessing is necessary. const original = this.get('attributes'); + + if (!original) { + return; + } + + // `unflatten` doesn't sort keys before unflattening, so manual preprocessing is necessary. const attrs = Object.keys(original) .sort() .reduce((obj, key) => { diff --git a/ui/app/models/node.js b/ui/app/models/node.js index 56e489e1d..74feacb4e 100644 --- a/ui/app/models/node.js +++ b/ui/app/models/node.js @@ -20,6 +20,7 @@ export default Model.extend({ httpAddr: attr('string'), tlsEnabled: attr('boolean'), attributes: fragment('node-attributes'), + meta: fragment('node-attributes'), resources: fragment('resources'), reserved: fragment('resources'), diff --git a/ui/app/templates/clients/client.hbs b/ui/app/templates/clients/client.hbs index 09423d9d4..132762710 100644 --- a/ui/app/templates/clients/client.hbs +++ b/ui/app/templates/clients/client.hbs @@ -84,6 +84,24 @@ attributes=model.attributes.attributesStructured class="attributes-table"}} +
+ Meta +
+ {{#if model.meta.attributesStructured}} +
+ {{attributes-table + data-test-meta + attributes=model.meta.attributesStructured + class="attributes-table"}} +
+ {{else}} +
+
+

No Meta Attributes

+

This client is configured with no meta attributes.

+
+
+ {{/if}} {{/gutter-menu}} diff --git a/ui/mirage/factories/node.js b/ui/mirage/factories/node.js index 3693171a6..ba4bd569e 100644 --- a/ui/mirage/factories/node.js +++ b/ui/mirage/factories/node.js @@ -58,6 +58,14 @@ export default Factory.extend({ }; }, + withMeta: trait({ + meta: { + just: 'some', + prop: 'erties', + 'over.here': 100, + }, + }), + afterCreate(node, server) { // Each node has a corresponding client stats resource that's queried via node IP. // Create that record, even though it's not a relationship. diff --git a/ui/tests/acceptance/client-detail-test.js b/ui/tests/acceptance/client-detail-test.js index 1b0788b00..0c733750b 100644 --- a/ui/tests/acceptance/client-detail-test.js +++ b/ui/tests/acceptance/client-detail-test.js @@ -197,9 +197,7 @@ test('each allocation should have high-level details for the allocation', functi }); }); -test('each allocation should show job information even if the job is incomplete and already in the store', function( - assert -) { +test('each allocation should show job information even if the job is incomplete and already in the store', function(assert) { // First, visit clients to load the allocations for each visible node. // Don't load the job belongsTo of the allocation! Leave it unfulfilled. @@ -288,9 +286,39 @@ test('/clients/:id should list all attributes for the node', function(assert) { }); }); -test('when the node is not found, an error message is shown, but the URL persists', function( - assert -) { +test('/clients/:id lists all meta attributes', function(assert) { + node = server.create('node', 'forceIPv4', 'withMeta'); + + visit(`/clients/${node.id}`); + + andThen(() => { + assert.ok(find('[data-test-meta]'), 'Meta attributes table is on the page'); + assert.notOk(find('[data-test-empty-meta-message]'), 'Meta attributes is not empty'); + + const firstMetaKey = Object.keys(node.meta)[0]; + assert.equal( + find('[data-test-meta] [data-test-key]').textContent.trim(), + firstMetaKey, + 'Meta attributes for the node are bound to the attributes table' + ); + assert.equal( + find('[data-test-meta] [data-test-value]').textContent.trim(), + node.meta[firstMetaKey], + 'Meta attributes for the node are bound to the attributes table' + ); + }); +}); + +test('/clients/:id shows an empty message when there is no meta data', function(assert) { + visit(`/clients/${node.id}`); + + andThen(() => { + assert.notOk(find('[data-test-meta]'), 'Meta attributes table is not on the page'); + assert.ok(find('[data-test-empty-meta-message]'), 'Meta attributes is empty'); + }); +}); + +test('when the node is not found, an error message is shown, but the URL persists', function(assert) { visit('/clients/not-a-real-node'); andThen(() => {