From dcb9800442fa0d1f3983911d6341d5c10efff972 Mon Sep 17 00:00:00 2001 From: John Cowen Date: Fri, 5 Jul 2019 09:07:25 +0100 Subject: [PATCH] ui: Gateway Addresses (#6075) - Removes 'type' icons (basically the proxy icon, not the text itself) - Add support for Mesh Gateways plus their addresses This adds a 'Mesh Gateway' type label to service and service instance pages, plus a new 'Addresses' tab if the service is a Mesh Gateway showing a table of addresses for the service - plus tests --- ui-v2/app/controllers/dc/services/index.js | 2 +- ui-v2/app/helpers/object-entries.js | 7 ++++ ui-v2/app/models/service.js | 1 + ui-v2/app/routes/dc/services/instance.js | 3 +- ui-v2/app/styles/components/app-view.scss | 7 +++- ui-v2/app/styles/components/table.scss | 6 --- .../styles/components/type-icon/index.scss | 2 - .../styles/components/type-icon/layout.scss | 5 --- .../app/styles/components/type-icon/skin.scss | 6 --- ui-v2/app/styles/core/typography.scss | 5 +-- ui-v2/app/styles/routes/dc/service/index.scss | 1 + .../app/templates/dc/services/-addresses.hbs | 25 +++++++++++++ ui-v2/app/templates/dc/services/index.hbs | 8 ---- ui-v2/app/templates/dc/services/instance.hbs | 32 ++++++++++++---- ui-v2/app/templates/dc/services/show.hbs | 2 + .../dc/services/instances/gateway.feature | 37 +++++++++++++++++++ .../dc/services/instances/gateway-steps.js | 10 +++++ .../helpers/object-entries-test.js | 20 ++++++++++ ui-v2/tests/pages/dc/services/instance.js | 5 ++- 19 files changed, 141 insertions(+), 43 deletions(-) create mode 100644 ui-v2/app/helpers/object-entries.js delete mode 100644 ui-v2/app/styles/components/type-icon/index.scss delete mode 100644 ui-v2/app/styles/components/type-icon/layout.scss delete mode 100644 ui-v2/app/styles/components/type-icon/skin.scss create mode 100644 ui-v2/app/templates/dc/services/-addresses.hbs create mode 100644 ui-v2/tests/acceptance/dc/services/instances/gateway.feature create mode 100644 ui-v2/tests/acceptance/steps/dc/services/instances/gateway-steps.js create mode 100644 ui-v2/tests/integration/helpers/object-entries-test.js diff --git a/ui-v2/app/controllers/dc/services/index.js b/ui-v2/app/controllers/dc/services/index.js index e8bfff9a45..326aaf85ee 100644 --- a/ui-v2/app/controllers/dc/services/index.js +++ b/ui-v2/app/controllers/dc/services/index.js @@ -57,7 +57,7 @@ export default Controller.extend(WithEventSource, WithSearching, { // take that off 50% (100% / number of fluid columns) // also we added a Type column which we've currently fixed to 100px // so again divide that by 2 and take it off each fluid column - return htmlSafe(`width: calc(50% - 50px - ${Math.round(get(this, 'maxWidth') / 2)}px)`); + return htmlSafe(`width: calc(50% - ${Math.round(get(this, 'maxWidth') / 2)}px)`); }), maxPassing: computed('items.[]', function() { return max(get(this, 'items'), 'ChecksPassing'); diff --git a/ui-v2/app/helpers/object-entries.js b/ui-v2/app/helpers/object-entries.js new file mode 100644 index 0000000000..f2ba716acd --- /dev/null +++ b/ui-v2/app/helpers/object-entries.js @@ -0,0 +1,7 @@ +import { helper } from '@ember/component/helper'; + +export function objectEntries([obj = {}] /*, hash*/) { + return Object.entries(obj); +} + +export default helper(objectEntries); diff --git a/ui-v2/app/models/service.js b/ui-v2/app/models/service.js index 3d7e425928..6e0092e5f8 100644 --- a/ui-v2/app/models/service.js +++ b/ui-v2/app/models/service.js @@ -17,6 +17,7 @@ export default Model.extend({ ExternalSources: attr(), Meta: attr(), Address: attr('string'), + TaggedAddresses: attr(), Port: attr('number'), EnableTagOverride: attr('boolean'), CreateIndex: attr('number'), diff --git a/ui-v2/app/routes/dc/services/instance.js b/ui-v2/app/routes/dc/services/instance.js index 4cd467b073..6d27b51083 100644 --- a/ui-v2/app/routes/dc/services/instance.js +++ b/ui-v2/app/routes/dc/services/instance.js @@ -18,7 +18,8 @@ export default Route.extend({ // connect-proxy or vice versa so leave as is for now return hash({ proxy: - get(model.item, 'Kind') === 'connect-proxy' + // proxies and mesh-gateways can't have proxies themselves so don't even look + ['connect-proxy', 'mesh-gateway'].includes(get(model.item, 'Kind')) ? null : proxyRepo.findInstanceBySlug(params.id, params.node, params.name, dc), ...model, diff --git a/ui-v2/app/styles/components/app-view.scss b/ui-v2/app/styles/components/app-view.scss index 7cd6562ee1..359583699a 100644 --- a/ui-v2/app/styles/components/app-view.scss +++ b/ui-v2/app/styles/components/app-view.scss @@ -1,7 +1,6 @@ @import './app-view/index'; @import './filter-bar/index'; @import './buttons/index'; -@import './type-icon/index'; main { @extend %app-view; } @@ -24,7 +23,11 @@ main { margin-top: 20px; } %app-view h1 span.kind-proxy { - @extend %type-icon, %with-proxy; + @extend %frame-gray-900; + @extend %pill; +} +%app-view h1 span.kind-proxy::before { + width: 0.3em !important; } %app-view h1 em { color: $gray-600; diff --git a/ui-v2/app/styles/components/table.scss b/ui-v2/app/styles/components/table.scss index 207a7ef4a6..760a7799e0 100644 --- a/ui-v2/app/styles/components/table.scss +++ b/ui-v2/app/styles/components/table.scss @@ -1,6 +1,5 @@ @import './icons/index'; @import './table/index'; -@import './type-icon/index'; html.template-service.template-list td:first-child a span, html.template-node.template-show #services td:first-child a span, @@ -20,11 +19,6 @@ html.template-service.template-list main th:first-child { td.folder { @extend %with-folder; } -td .kind-proxy { - @extend %type-icon, %with-proxy; - text-indent: -9000px !important; - width: 24px; -} table:not(.sessions) tbody tr { cursor: pointer; } diff --git a/ui-v2/app/styles/components/type-icon/index.scss b/ui-v2/app/styles/components/type-icon/index.scss deleted file mode 100644 index bc18252196..0000000000 --- a/ui-v2/app/styles/components/type-icon/index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './skin'; -@import './layout'; diff --git a/ui-v2/app/styles/components/type-icon/layout.scss b/ui-v2/app/styles/components/type-icon/layout.scss deleted file mode 100644 index a88b65d79e..0000000000 --- a/ui-v2/app/styles/components/type-icon/layout.scss +++ /dev/null @@ -1,5 +0,0 @@ -%type-icon { - display: inline-block; - text-indent: 20px; - padding: 3px; -} diff --git a/ui-v2/app/styles/components/type-icon/skin.scss b/ui-v2/app/styles/components/type-icon/skin.scss deleted file mode 100644 index b6d0be1129..0000000000 --- a/ui-v2/app/styles/components/type-icon/skin.scss +++ /dev/null @@ -1,6 +0,0 @@ -%type-icon { - border-radius: 4px; - - background: $gray-100; - color: $gray-400; -} diff --git a/ui-v2/app/styles/core/typography.scss b/ui-v2/app/styles/core/typography.scss index 8b5eeeed2c..9a0662f9c4 100644 --- a/ui-v2/app/styles/core/typography.scss +++ b/ui-v2/app/styles/core/typography.scss @@ -65,8 +65,7 @@ td strong, %breadcrumbs li > *, %action-group-action, %tab-nav, -%tooltip-bubble, -%type-icon { +%tooltip-bubble { font-weight: $typo-weight-medium; } @@ -113,7 +112,7 @@ caption, %tooltip-bubble, %healthchecked-resource strong, %footer, -%type-icon { +%app-view h1 span.kind-proxy { font-size: $typo-size-700; } %toggle label span { diff --git a/ui-v2/app/styles/routes/dc/service/index.scss b/ui-v2/app/styles/routes/dc/service/index.scss index fd6734b7b3..07ac540244 100644 --- a/ui-v2/app/styles/routes/dc/service/index.scss +++ b/ui-v2/app/styles/routes/dc/service/index.scss @@ -1,3 +1,4 @@ +html.template-instance.template-show #addresses table tr, html.template-instance.template-show #upstreams table tr { cursor: default; } diff --git a/ui-v2/app/templates/dc/services/-addresses.hbs b/ui-v2/app/templates/dc/services/-addresses.hbs new file mode 100644 index 0000000000..4321d43f0d --- /dev/null +++ b/ui-v2/app/templates/dc/services/-addresses.hbs @@ -0,0 +1,25 @@ +{{#if item.TaggedAddresses }} +{{#tabular-collection + data-test-addresses + items=(object-entries item.TaggedAddresses) as |taggedAddress index| +}} + {{#block-slot 'header'}} + Tag + Address + {{/block-slot}} + {{#block-slot 'row'}} +{{#with (object-at 1 taggedAddress) as |address|}} + + {{object-at 0 taggedAddress}}{{#if (and (eq address.Address item.Address) (eq address.Port item.Port))}} (default){{/if}} + + + {{address.Address}}:{{address.Port}} + +{{/with}} + {{/block-slot}} +{{/tabular-collection}} +{{else}} +

+ There are no additional addresses. +

+{{/if}} diff --git a/ui-v2/app/templates/dc/services/index.hbs b/ui-v2/app/templates/dc/services/index.hbs index 6812f5a6af..a2534e03b9 100644 --- a/ui-v2/app/templates/dc/services/index.hbs +++ b/ui-v2/app/templates/dc/services/index.hbs @@ -23,7 +23,6 @@ }} {{#block-slot 'header'}} Service - Type Health ChecksThe number of health checks for the service on all nodes Tags {{/block-slot}} @@ -34,13 +33,6 @@ {{item.Name}} - -{{#if (eq item.Kind 'connect-proxy')}} - Proxy -{{else}} -   -{{/if}} - {{healthcheck-info passing=item.ChecksPassing warning=item.ChecksWarning critical=item.ChecksCritical diff --git a/ui-v2/app/templates/dc/services/instance.hbs b/ui-v2/app/templates/dc/services/instance.hbs index 0f8372f6b6..d108dcfcfd 100644 --- a/ui-v2/app/templates/dc/services/instance.hbs +++ b/ui-v2/app/templates/dc/services/instance.hbs @@ -21,6 +21,8 @@ {{/with}} {{#if (eq item.Kind 'connect-proxy')}} Proxy +{{else if (eq item.Kind 'mesh-gateway')}} + Mesh Gateway {{/if}}
@@ -64,10 +66,17 @@ {{tab-nav items=(compact (array - 'Service Checks' - 'Node Checks' -(if (eq item.Kind 'connect-proxy') 'Upstreams' '') - 'Tags' + 'Service Checks' + 'Node Checks' +(if + (eq item.Kind 'connect-proxy') + 'Upstreams' '' +) +(if + (eq item.Kind 'mesh-gateway') + 'Addresses' '' +) + 'Tags' ) ) selected=selectedTab @@ -75,10 +84,17 @@ {{#each (compact (array - (hash id=(slugify 'Service Checks') partial='dc/services/servicechecks') - (hash id=(slugify 'Node Checks') partial='dc/services/nodechecks') -(if (eq item.Kind 'connect-proxy') (hash id=(slugify 'Upstreams') partial='dc/services/upstreams') '') - (hash id=(slugify 'Tags') partial='dc/services/tags') + (hash id=(slugify 'Service Checks') partial='dc/services/servicechecks') + (hash id=(slugify 'Node Checks') partial='dc/services/nodechecks') +(if + (eq item.Kind 'connect-proxy') + (hash id=(slugify 'Upstreams') partial='dc/services/upstreams') '' +) +(if + (eq item.Kind 'mesh-gateway') + (hash id=(slugify 'Addresses') partial='dc/services/addresses') '' +) + (hash id=(slugify 'Tags') partial='dc/services/tags') ) ) as |panel| }} diff --git a/ui-v2/app/templates/dc/services/show.hbs b/ui-v2/app/templates/dc/services/show.hbs index 53860f601a..af711eb1fc 100644 --- a/ui-v2/app/templates/dc/services/show.hbs +++ b/ui-v2/app/templates/dc/services/show.hbs @@ -19,6 +19,8 @@ {{/with}} {{#if (eq item.Service.Kind 'connect-proxy')}} Proxy +{{else if (eq item.Service.Kind 'mesh-gateway')}} + Mesh Gateway {{/if}} diff --git a/ui-v2/tests/acceptance/dc/services/instances/gateway.feature b/ui-v2/tests/acceptance/dc/services/instances/gateway.feature new file mode 100644 index 0000000000..09c4d404ef --- /dev/null +++ b/ui-v2/tests/acceptance/dc/services/instances/gateway.feature @@ -0,0 +1,37 @@ +@setupApplicationTest +Feature: dc / services / instances / gateway: Show Gateway Service Instance + Scenario: A Gateway Service instance + Given 1 datacenter model with the value "dc1" + And 1 instance model from yaml + --- + - Service: + Kind: mesh-gateway + Name: gateway + ID: gateway-with-id + TaggedAddresses: + lan: + Address: 127.0.0.1 + Port: 8080 + wan: + Address: 92.68.0.0 + Port: 8081 + --- + When I visit the instance page for yaml + --- + dc: dc1 + service: gateway + node: node-0 + id: gateway-with-id + --- + Then the url should be /dc1/services/gateway/node-0/gateway-with-id + + And I see serviceChecksIsSelected on the tabs + + When I click addresses on the tabs + And I see addressesIsSelected on the tabs + And I see 2 of the addresses object + And I see address on the addresses like yaml + --- + - 127.0.0.1:8080 + - 92.68.0.0:8081 + --- diff --git a/ui-v2/tests/acceptance/steps/dc/services/instances/gateway-steps.js b/ui-v2/tests/acceptance/steps/dc/services/instances/gateway-steps.js new file mode 100644 index 0000000000..9bfbe9ac9b --- /dev/null +++ b/ui-v2/tests/acceptance/steps/dc/services/instances/gateway-steps.js @@ -0,0 +1,10 @@ +import steps from '../../../steps'; + +// step definitions that are shared between features should be moved to the +// tests/acceptance/steps/steps.js file + +export default function(assert) { + return steps(assert).then('I should find a file', function() { + assert.ok(true, this.step); + }); +} diff --git a/ui-v2/tests/integration/helpers/object-entries-test.js b/ui-v2/tests/integration/helpers/object-entries-test.js new file mode 100644 index 0000000000..b108d6584c --- /dev/null +++ b/ui-v2/tests/integration/helpers/object-entries-test.js @@ -0,0 +1,20 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('object-entries', 'helper:object-entries', { + integration: true, +}); + +// Replace this with your real tests. +test('it renders', function(assert) { + this.set('inputValue', '1234'); + + this.render(hbs`{{object-entries inputValue}}`); + + assert.equal( + this.$() + .text() + .trim(), + Object.entries('1234').toString() + ); +}); diff --git a/ui-v2/tests/pages/dc/services/instance.js b/ui-v2/tests/pages/dc/services/instance.js index a728fad7fe..667e92e190 100644 --- a/ui-v2/tests/pages/dc/services/instance.js +++ b/ui-v2/tests/pages/dc/services/instance.js @@ -2,7 +2,7 @@ export default function(visitable, attribute, collection, text, radiogroup) { return { visit: visitable('/:dc/services/:service/:node/:id'), externalSource: attribute('data-test-external-source', 'h1 span'), - tabs: radiogroup('tab', ['service-checks', 'node-checks', 'upstreams', 'tags']), + tabs: radiogroup('tab', ['service-checks', 'node-checks', 'addresses', 'upstreams', 'tags']), serviceChecks: collection('#service-checks [data-test-healthchecks] li', {}), nodeChecks: collection('#node-checks [data-test-healthchecks] li', {}), upstreams: collection('#upstreams [data-test-tabular-row]', { @@ -11,6 +11,9 @@ export default function(visitable, attribute, collection, text, radiogroup) { type: text('[data-test-destination-type]'), address: text('[data-test-local-bind-address]'), }), + addresses: collection('#addresses [data-test-tabular-row]', { + address: text('[data-test-address]'), + }), proxy: { type: attribute('data-test-proxy-type', '[data-test-proxy-type]'), destination: attribute('data-test-proxy-destination', '[data-test-proxy-destination]'),