diff --git a/ui-v2/app/components/consul-instance-checks/index.hbs b/ui-v2/app/components/consul-instance-checks/index.hbs new file mode 100644 index 000000000..937b2942d --- /dev/null +++ b/ui-v2/app/components/consul-instance-checks/index.hbs @@ -0,0 +1,32 @@ +{{#if (gt items.length 0)}} + {{#if (eq healthCheck.check 'empty') }} +
+
+ + {{capitalize type}} Checks + +
+
No {{type}} checks
+
+ {{else}} + {{#if (eq healthCheck.count items.length)}} +
+
+ + {{capitalize type}} Checks + +
+
All {{type}} checks {{healthCheck.status}}
+
+ {{else}} +
+
+ + {{capitalize type}} Checks + +
+
{{healthCheck.count}}/{{items.length}} {{type}} checks {{healthCheck.status}}
+
+ {{/if}} + {{/if}} +{{/if}} \ No newline at end of file diff --git a/ui-v2/app/components/consul-instance-checks/index.js b/ui-v2/app/components/consul-instance-checks/index.js new file mode 100644 index 000000000..da5c60aa0 --- /dev/null +++ b/ui-v2/app/components/consul-instance-checks/index.js @@ -0,0 +1,52 @@ +import Component from '@ember/component'; +import { computed } from '@ember/object'; + +export default Component.extend({ + tagName: '', + healthCheck: computed('items.[]', function() { + let ChecksCritical = 0; + let ChecksWarning = 0; + let ChecksPassing = 0; + + this.items.forEach(item => { + switch (item.Status) { + case 'critical': + ChecksCritical += 1; + break; + case 'warning': + ChecksWarning += 1; + break; + case 'passing': + ChecksPassing += 1; + break; + default: + break; + } + }); + + switch (true) { + case ChecksCritical !== 0: + return { + check: 'critical', + status: 'failing', + count: ChecksCritical, + }; + case ChecksWarning !== 0: + return { + check: 'warning', + status: 'with warning', + count: ChecksWarning, + }; + case ChecksPassing !== 0: + return { + check: 'passing', + status: 'passing', + count: ChecksPassing, + }; + default: + return { + check: 'empty', + }; + } + }), +}); diff --git a/ui-v2/app/components/consul-service-instance-list/index.hbs b/ui-v2/app/components/consul-service-instance-list/index.hbs index df8d294c2..a218f5095 100644 --- a/ui-v2/app/components/consul-service-instance-list/index.hbs +++ b/ui-v2/app/components/consul-service-instance-list/index.hbs @@ -1,80 +1,25 @@ {{#if (gt items.length 0)}} - - {{item.Service.ID}} - + {{#if (eq routeName "dc.services.show")}} + + {{item.ID}} + + {{else}} + + {{item.Service.ID}} + + {{/if}} + {{#if checks}} + + + {{else}} -{{#let (reject-by 'ServiceID' '' item.Checks) as |checks|}} - {{#let (service/instance-checks checks) as |serviceCheck| }} - {{#if (eq serviceCheck.check 'empty') }} -
-
- - Service Checks - -
-
No service checks
-
- {{else}} - {{#if (eq serviceCheck.count checks.length)}} -
-
- - Service Checks - -
-
All service checks {{serviceCheck.status}}
-
- {{else}} -
-
- - Service Checks - -
-
{{serviceCheck.count}}/{{checks.length}} service checks {{serviceCheck.status}}
-
- {{/if}} + + {{/if}} - {{/let}} -{{/let}} -{{#let (filter-by 'ServiceID' '' item.Checks) as |checks|}} - {{#let (service/instance-checks checks) as |nodeCheck| }} - {{#if (eq nodeCheck.check 'empty') }} -
-
- - Node Checks - -
-
No node checks
-
- {{else}} - {{#if (eq nodeCheck.count checks.length)}} -
-
- - Node Checks - -
-
All node checks {{nodeCheck.status}}
-
- {{else}} -
-
- - Node Checks - -
-
{{nodeCheck.count}}/{{checks.length}} node checks {{nodeCheck.status}}
-
- {{/if}} - {{/if}} - {{/let}} -{{/let}} {{#if (get proxies item.Service.ID)}}
@@ -99,6 +44,7 @@
{{/if}} +{{#if item.Service.Port}}
@@ -113,7 +59,23 @@ {{/if}}
+{{/if}} +{{#if (and checks item.Port)}} +
+
+ +
+
:{{item.Port}}
+
+{{/if}} +{{#if checks}} + +{{else}} +{{/if}}
{{/if}} \ No newline at end of file diff --git a/ui-v2/app/controllers/dc/nodes/show/services.js b/ui-v2/app/controllers/dc/nodes/show/services.js index d313ad8b8..005114add 100644 --- a/ui-v2/app/controllers/dc/nodes/show/services.js +++ b/ui-v2/app/controllers/dc/nodes/show/services.js @@ -1,5 +1,6 @@ import Controller from '@ember/controller'; import { alias } from '@ember/object/computed'; +import { get, computed } from '@ember/object'; export default Controller.extend({ items: alias('item.Services'), @@ -9,4 +10,19 @@ export default Controller.extend({ replace: true, }, }, + checks: computed('item.Checks.[]', function() { + const checks = {}; + get(this, 'item.Checks') + .filter(item => { + return item.ServiceID !== ''; + }) + .forEach(item => { + if (typeof checks[item.ServiceID] === 'undefined') { + checks[item.ServiceID] = []; + } + checks[item.ServiceID].push(item); + }); + + return checks; + }), }); diff --git a/ui-v2/app/helpers/service/instance-checks.js b/ui-v2/app/helpers/service/instance-checks.js deleted file mode 100644 index 319e82bf1..000000000 --- a/ui-v2/app/helpers/service/instance-checks.js +++ /dev/null @@ -1,50 +0,0 @@ -import { helper } from '@ember/component/helper'; - -export function healthChecks([items], hash) { - let ChecksCritical = 0; - let ChecksWarning = 0; - let ChecksPassing = 0; - - items.forEach(item => { - switch (item.Status) { - case 'critical': - ChecksCritical += 1; - break; - case 'warning': - ChecksWarning += 1; - break; - case 'passing': - ChecksPassing += 1; - break; - default: - break; - } - }); - - switch (true) { - case ChecksCritical !== 0: - return { - check: 'critical', - status: 'failing', - count: ChecksCritical, - }; - case ChecksWarning !== 0: - return { - check: 'warning', - status: 'with warning', - count: ChecksWarning, - }; - case ChecksPassing !== 0: - return { - check: 'passing', - status: 'passing', - count: ChecksPassing, - }; - default: - return { - check: 'empty', - }; - } -} - -export default helper(healthChecks); diff --git a/ui-v2/app/router.js b/ui-v2/app/router.js index 5114afc21..b0dce2236 100644 --- a/ui-v2/app/router.js +++ b/ui-v2/app/router.js @@ -67,7 +67,7 @@ export const routes = { _options: { path: '/health-checks' }, }, services: { - _options: { path: '/services' }, + _options: { path: '/service-instances' }, }, rtt: { _options: { path: '/round-trip-time' }, diff --git a/ui-v2/app/styles/components/composite-row/layout.scss b/ui-v2/app/styles/components/composite-row/layout.scss index 3dd4dfddc..13ffdf545 100644 --- a/ui-v2/app/styles/components/composite-row/layout.scss +++ b/ui-v2/app/styles/components/composite-row/layout.scss @@ -73,6 +73,7 @@ } %composite-row-detail .copy-button { margin-right: 4px; + margin-top: 2px; } %composite-row-header .copy-button { margin-left: 4px; diff --git a/ui-v2/app/templates/dc/nodes/show.hbs b/ui-v2/app/templates/dc/nodes/show.hbs index 624c5b67c..c04813ac0 100644 --- a/ui-v2/app/templates/dc/nodes/show.hbs +++ b/ui-v2/app/templates/dc/nodes/show.hbs @@ -21,7 +21,7 @@ compact (array (hash label="Health Checks" href=(href-to "dc.nodes.show.healthchecks") selected=(is-href "dc.nodes.show.healthchecks")) - (hash label="Services" href=(href-to "dc.nodes.show.services") selected=(is-href "dc.nodes.show.services")) + (hash label="Service Instances" href=(href-to "dc.nodes.show.services") selected=(is-href "dc.nodes.show.services")) (if tomography.distances (hash label="Round Trip Time" href=(href-to "dc.nodes.show.rtt") selected=(is-href "dc.nodes.show.rtt")) '') (hash label="Lock Sessions" href=(href-to "dc.nodes.show.sessions") selected=(is-href "dc.nodes.show.sessions")) (hash label="Metadata" href=(href-to "dc.nodes.show.metadata") selected=(is-href "dc.nodes.show.metadata")) diff --git a/ui-v2/app/templates/dc/nodes/show/services.hbs b/ui-v2/app/templates/dc/nodes/show/services.hbs index f677a1ae6..ab0736125 100644 --- a/ui-v2/app/templates/dc/nodes/show/services.hbs +++ b/ui-v2/app/templates/dc/nodes/show/services.hbs @@ -8,38 +8,9 @@ @onsearch={{action (mut search) value="target.value"}} /> {{/if}} - + - - - Service - Port - Tags - - - - - {{#let (service/external-source item) as |externalSource| }} - {{#if externalSource }} - - {{else}} - - {{/if}} - {{/let}} - {{item.Service}}{{#if (not-eq item.ID item.Service) }} ({{item.ID}}){{/if}} - - - - {{item.Port}} - - - - - - +

diff --git a/ui-v2/tests/acceptance/components/catalog-filter.feature b/ui-v2/tests/acceptance/components/catalog-filter.feature index 552816415..68b9e02c5 100644 --- a/ui-v2/tests/acceptance/components/catalog-filter.feature +++ b/ui-v2/tests/acceptance/components/catalog-filter.feature @@ -90,8 +90,8 @@ Feature: components / catalog-filter node: node-0 --- # And I see 3 healthcheck model with the name "Disk Util" - When I click services on the tabs - And I see servicesIsSelected on the tabs + When I click serviceInstances on the tabs + And I see serviceInstancesIsSelected on the tabs Then I fill in with yaml --- @@ -101,12 +101,6 @@ Feature: components / catalog-filter And I see 1 [Model] model with the port "65535" Then I fill in with yaml --- - s: service-0-with-id - --- - And I see 1 [Model] model - And I see 1 [Model] model with the id "service-0-with-id" - Then I fill in with yaml - --- s: hard drive --- And I see 1 [Model] model with the name "[Model]-1" diff --git a/ui-v2/tests/acceptance/dc/nodes/services/list.feature b/ui-v2/tests/acceptance/dc/nodes/services/list.feature index 1d99fd9f9..e7c6010df 100644 --- a/ui-v2/tests/acceptance/dc/nodes/services/list.feature +++ b/ui-v2/tests/acceptance/dc/nodes/services/list.feature @@ -30,24 +30,18 @@ Feature: dc / nodes / services / list: Node > Services Listing Tags: [] Meta: external-source: kubernetes - - ID: 'service-4' - Port: 3 - Service: 'service-4' - Tags: [] - Meta: ~ --- When I visit the node page for yaml --- dc: dc1 node: node-0 --- - When I click services on the tabs - And I see servicesIsSelected on the tabs + When I click serviceInstances on the tabs + And I see serviceInstancesIsSelected on the tabs And I see externalSource on the services like yaml --- - consul - nomad - terraform - kubernetes - - ~ --- diff --git a/ui-v2/tests/acceptance/dc/nodes/show.feature b/ui-v2/tests/acceptance/dc/nodes/show.feature index d40300141..00e0b896d 100644 --- a/ui-v2/tests/acceptance/dc/nodes/show.feature +++ b/ui-v2/tests/acceptance/dc/nodes/show.feature @@ -11,8 +11,8 @@ Feature: dc / nodes / show: Show node --- And I see healthChecksIsSelected on the tabs - When I click services on the tabs - And I see servicesIsSelected on the tabs + When I click serviceInstances on the tabs + And I see serviceInstancesIsSelected on the tabs When I click roundTripTime on the tabs And I see roundTripTimeIsSelected on the tabs @@ -34,14 +34,14 @@ Feature: dc / nodes / show: Show node --- And I see healthChecksIsSelected on the tabs - When I click services on the tabs - And I see servicesIsSelected on the tabs + When I click serviceInstances on the tabs + And I see serviceInstancesIsSelected on the tabs And I don't see roundTripTime on the tabs When I click lockSessions on the tabs And I see lockSessionsIsSelected on the tabs - Scenario: Given 1 node with no checks all the tabs are visible but the Services tab is selected + Scenario: Given 1 node with no checks all the tabs are visible but the serviceInstances tab is selected Given 1 node models from yaml --- ID: node-0 @@ -53,10 +53,10 @@ Feature: dc / nodes / show: Show node node: node-0 --- And I see healthChecks on the tabs - And I see services on the tabs + And I see serviceInstances on the tabs And I don't see roundTripTime on the tabs And I see lockSessions on the tabs - And I see servicesIsSelected on the tabs + And I see serviceInstancesIsSelected on the tabs Scenario: A node warns when deregistered whilst blocking Given 1 node model from yaml --- diff --git a/ui-v2/tests/integration/components/consul-instance-checks-test.js b/ui-v2/tests/integration/components/consul-instance-checks-test.js new file mode 100644 index 000000000..efd334c0f --- /dev/null +++ b/ui-v2/tests/integration/components/consul-instance-checks-test.js @@ -0,0 +1,25 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | consul-instance-checks', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.set('myAction', function(val) { ... }); + + await render(hbs``); + + assert.equal(this.element.textContent.trim(), ''); + + // Template block usage: + await render(hbs` + + + `); + + assert.equal(this.element.textContent.trim(), ''); + }); +}); diff --git a/ui-v2/tests/pages.js b/ui-v2/tests/pages.js index 33bd49153..961346b49 100644 --- a/ui-v2/tests/pages.js +++ b/ui-v2/tests/pages.js @@ -138,7 +138,7 @@ export default { ), instance: create(instance(visitable, attribute, collection, text, tabgroup)), nodes: create(nodes(visitable, clickable, attribute, collection, catalogFilter)), - node: create(node(visitable, deletable, clickable, attribute, collection, tabgroup)), + node: create(node(visitable, deletable, clickable, attribute, collection, tabgroup, text)), kvs: create(kvs(visitable, deletable, creatable, clickable, attribute, collection)), kv: create(kv(visitable, attribute, submitable, deletable, cancelable, clickable)), acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)), diff --git a/ui-v2/tests/pages/dc/nodes/show.js b/ui-v2/tests/pages/dc/nodes/show.js index aad9470f7..a5afb1c9f 100644 --- a/ui-v2/tests/pages/dc/nodes/show.js +++ b/ui-v2/tests/pages/dc/nodes/show.js @@ -1,9 +1,9 @@ -export default function(visitable, deletable, clickable, attribute, collection, tabs) { +export default function(visitable, deletable, clickable, attribute, collection, tabs, text) { return { visit: visitable('/:dc/nodes/:node'), tabs: tabs('tab', [ 'health-checks', - 'services', + 'service-instances', 'round-trip-time', 'lock-sessions', 'metadata', @@ -11,11 +11,10 @@ export default function(visitable, deletable, clickable, attribute, collection, healthchecks: collection('[data-test-node-healthcheck]', { name: attribute('data-test-node-healthcheck'), }), - services: collection('#services [data-test-tabular-row]', { - id: attribute('data-test-service-id', '[data-test-service-id]'), - name: attribute('data-test-service-name', '[data-test-service-name]'), - port: attribute('data-test-service-port', '.port'), - externalSource: attribute('data-test-external-source', 'a span'), + services: collection('.consul-service-instance-list > ul > li:not(:first-child)', { + name: text('[data-test-service-name]'), + port: attribute('data-test-service-port', '[data-test-service-port]'), + externalSource: attribute('data-test-external-source', '[data-test-external-source]'), }), sessions: collection( '#lock-sessions [data-test-tabular-row]', diff --git a/ui-v2/yarn.lock b/ui-v2/yarn.lock index 980290294..a41d77881 100644 --- a/ui-v2/yarn.lock +++ b/ui-v2/yarn.lock @@ -1211,9 +1211,9 @@ js-yaml "^3.13.1" "@hashicorp/consul-api-double@^3.0.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@hashicorp/consul-api-double/-/consul-api-double-3.1.2.tgz#3c3b929ab0f8aff5f503728337caf1c1a41171fb" - integrity sha512-igs6f9fiA+z2Us1oLZ49/sEU0WsL+s7a1pnwFtED2xdI8tn5hz9G0doYfOxmi04IifNxv80NVifl3rZl2rn2tw== + version "3.1.3" + resolved "https://registry.yarnpkg.com/@hashicorp/consul-api-double/-/consul-api-double-3.1.3.tgz#62f8780c8513e9b37f29302543c29143b4024141" + integrity sha512-IZ90RK8g4/QPxQpRLnatwpBQh9Z3kQJjOGiUVz+CrSlXg4KRLhQCFFz/gI2vmhAXRACyTxIWuydPV6BcN4ptZA== "@hashicorp/ember-cli-api-double@^3.1.0": version "3.1.0"