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
This commit is contained in:
parent
35a839952b
commit
b143a3bb66
|
@ -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');
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import { helper } from '@ember/component/helper';
|
||||
|
||||
export function objectEntries([obj = {}] /*, hash*/) {
|
||||
return Object.entries(obj);
|
||||
}
|
||||
|
||||
export default helper(objectEntries);
|
|
@ -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'),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
@import './skin';
|
||||
@import './layout';
|
|
@ -1,5 +0,0 @@
|
|||
%type-icon {
|
||||
display: inline-block;
|
||||
text-indent: 20px;
|
||||
padding: 3px;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
%type-icon {
|
||||
border-radius: 4px;
|
||||
|
||||
background: $gray-100;
|
||||
color: $gray-400;
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
html.template-instance.template-show #addresses table tr,
|
||||
html.template-instance.template-show #upstreams table tr {
|
||||
cursor: default;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
{{#if item.TaggedAddresses }}
|
||||
{{#tabular-collection
|
||||
data-test-addresses
|
||||
items=(object-entries item.TaggedAddresses) as |taggedAddress index|
|
||||
}}
|
||||
{{#block-slot 'header'}}
|
||||
<th>Tag</th>
|
||||
<th>Address</th>
|
||||
{{/block-slot}}
|
||||
{{#block-slot 'row'}}
|
||||
{{#with (object-at 1 taggedAddress) as |address|}}
|
||||
<td>
|
||||
{{object-at 0 taggedAddress}}{{#if (and (eq address.Address item.Address) (eq address.Port item.Port))}} <em data-test-address-default>(default)</em>{{/if}}
|
||||
</td>
|
||||
<td data-test-address>
|
||||
{{address.Address}}:{{address.Port}}
|
||||
</td>
|
||||
{{/with}}
|
||||
{{/block-slot}}
|
||||
{{/tabular-collection}}
|
||||
{{else}}
|
||||
<p>
|
||||
There are no additional addresses.
|
||||
</p>
|
||||
{{/if}}
|
|
@ -23,7 +23,6 @@
|
|||
}}
|
||||
{{#block-slot 'header'}}
|
||||
<th style={{remainingWidth}}>Service</th>
|
||||
<th>Type</th>
|
||||
<th style={{totalWidth}}>Health Checks<span><em>The number of health checks for the service on all nodes</em></span></th>
|
||||
<th style={{remainingWidth}}>Tags</th>
|
||||
{{/block-slot}}
|
||||
|
@ -34,13 +33,6 @@
|
|||
{{item.Name}}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{#if (eq item.Kind 'connect-proxy')}}
|
||||
<span class="kind-proxy">Proxy</span>
|
||||
{{else}}
|
||||
|
||||
{{/if}}
|
||||
</td>
|
||||
<td style={{totalWidth}}>
|
||||
{{healthcheck-info
|
||||
passing=item.ChecksPassing warning=item.ChecksWarning critical=item.ChecksCritical
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
{{/with}}
|
||||
{{#if (eq item.Kind 'connect-proxy')}}
|
||||
<span class="kind-proxy">Proxy</span>
|
||||
{{else if (eq item.Kind 'mesh-gateway')}}
|
||||
<span class="kind-proxy">Mesh Gateway</span>
|
||||
{{/if}}
|
||||
</h1>
|
||||
<dl>
|
||||
|
@ -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|
|
||||
}}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
{{/with}}
|
||||
{{#if (eq item.Service.Kind 'connect-proxy')}}
|
||||
<span class="kind-proxy">Proxy</span>
|
||||
{{else if (eq item.Service.Kind 'mesh-gateway')}}
|
||||
<span class="kind-proxy">Mesh Gateway</span>
|
||||
{{/if}}
|
||||
</h1>
|
||||
<label for="toolbar-toggle"></label>
|
||||
|
|
|
@ -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
|
||||
---
|
|
@ -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);
|
||||
});
|
||||
}
|
|
@ -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()
|
||||
);
|
||||
});
|
|
@ -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]'),
|
||||
|
|
Loading…
Reference in New Issue