ui: Instance detail redesign (#7683)

* Remove Proxy link and add ExternalSource to instance detail page header

* Create HealthChecks tab with route and styling

* Fix up tests to fit redesign of Service Instances Detail page
This commit is contained in:
Kenia 2020-04-22 10:40:59 -04:00 committed by John Cowen
parent 2685c5081b
commit 8643565b30
20 changed files with 56 additions and 431 deletions

View File

@ -1,7 +1,7 @@
<ul data-test-healthchecks>
<ul>
{{#each (sort-by (action 'sortChecksByImportance') items) as |item| }}
{{! TODO: this component and its child should be moved to a single component }}
<HealthcheckOutput @data-test-node-healthcheck={{item.Name}} @class={{item.Status}} @tagName="li">
<HealthcheckOutput class={{item.Status}} @tagName="li">
<BlockSlot @name="header">
<h3>{{item.Name}}</h3>
</BlockSlot>

View File

@ -28,11 +28,8 @@ export const routes = {
},
instance: {
_options: { path: '/:name/instances/:node/:id' },
servicechecks: {
_options: { path: '/service-checks' },
},
nodechecks: {
_options: { path: '/node-checks' },
healthchecks: {
_options: { path: '/health-checks' },
},
upstreams: {
_options: { path: '/upstreams' },

View File

@ -2,5 +2,5 @@ import Route from '@ember/routing/route';
import to from 'consul-ui/utils/routing/redirect-to';
export default Route.extend({
redirect: to('servicechecks'),
redirect: to('healthchecks'),
});

View File

@ -1,14 +0,0 @@
import Route from '@ember/routing/route';
export default Route.extend({
model: function() {
const parent = this.routeName
.split('.')
.slice(0, -1)
.join('.');
return this.modelFor(parent);
},
setupController: function(controller, model) {
controller.setProperties(model);
},
});

View File

@ -13,7 +13,6 @@
@import 'core/layout';
@import 'routes/dc/settings/index';
@import 'routes/dc/service/index';
@import 'routes/dc/nodes/index';
@import 'routes/dc/intention/index';
@import 'routes/dc/kv/index';

View File

@ -16,3 +16,9 @@
padding-top: 13px;
padding-bottom: 13px;
}
%tab-section section h3 {
margin: 24px 0;
}
%tab-section section:not(:last-child) {
border-bottom: 1px solid $gray-200;
}

View File

@ -20,6 +20,9 @@
%app-view-header dt {
font-weight: bold;
}
%app-view-header dd > a {
color: $black;
}
%app-view-header .title-bar {
display: flex;
align-items: center;

View File

@ -1,9 +0,0 @@
/* TODO: need to standardize on the selectors used here */
/* I would guess at the time of writing this we shojuld prefer */
/* classes */
html.template-instance.template-show #addresses table tr,
html.template-instance.template-show #upstreams table tr,
html.template-instance.template-show #meta-data table tr,
html.template-instance.template-show table.exposedpaths tr {
cursor: default;
}

View File

@ -11,19 +11,12 @@
</ol>
</BlockSlot>
<BlockSlot @name="header">
<div class="title-bar">
<h1>
{{ item.ID }}
{{#let (service/external-source item) as |externalSource| }}
{{#if externalSource }}
<span data-test-external-source={{externalSource}} style={{concat 'background-image: var(--' externalSource '-icon)'}} data-tooltip="Registered via {{externalSource}}">Registered via {{externalSource}}</span>
{{/if}}
{{/let}}
{{#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>
<ConsulExternalSource @item={{item}} />
</div>
<dl>
<dt>Service Name</dt>
<dd><a href="{{href-to 'dc.services.show' item.Service}}">{{item.Service}}</a></dd>
@ -34,13 +27,6 @@
</dl>
{{#if proxy.ServiceName}}
<dl>
{{#if proxy.ServiceProxy.DestinationServiceID}}
<dt data-test-proxy-type="sidecar-proxy">Sidecar Proxy</dt>
<dd><a href="{{href-to 'dc.services.instance' proxy.ServiceName proxy.Node proxy.ServiceID}}">{{proxy.ServiceID}}</a></dd>
{{else}}
<dt data-test-proxy-type="proxy">Proxy</dt>
<dd><a href="{{href-to 'dc.services.show' proxy.ServiceName}}">{{proxy.ServiceName}}</a></dd>
{{/if}}
</dl>
{{/if}}
{{#if (eq item.Kind 'connect-proxy')}}
@ -65,8 +51,7 @@
<TabNav @items={{
compact
(array
(hash label="Service Checks" href=(href-to "dc.services.instance.servicechecks") selected=(is-href "dc.services.instance.servicechecks"))
(hash label="Node Checks" href=(href-to "dc.services.instance.nodechecks") selected=(is-href "dc.services.instance.nodechecks"))
(hash label="Health Checks" href=(href-to "dc.services.instance.healthchecks") selected=(is-href "dc.services.instance.healthchecks"))
(if
(eq item.Kind 'connect-proxy')
(hash label="Upstreams" href=(href-to "dc.services.instance.upstreams") selected=(is-href "dc.services.instance.upstreams")) ""

View File

@ -0,0 +1,24 @@
<div id="health-checks" class="tab-section">
<div role="tabpanel">
{{#if (gt item.ServiceChecks.length 0) }}
<section data-test-service-checks>
<h3>Service Checks</h3>
<HealthcheckList @items={{item.ServiceChecks}} @exposed={{proxy.ServiceProxy.Expose.Checks}} />
</section>
{{else}}
<p>
This instance has no service health checks.
</p>
{{/if}}
{{#if (gt item.NodeChecks.length 0) }}
<section data-test-node-checks>
<h3>Node Checks</h3>
<HealthcheckList @items={{item.NodeChecks}} />
</section>
{{else}}
<p>
This instance has no node health checks.
</p>
{{/if}}
</div>
</div>

View File

@ -1,12 +0,0 @@
<div id="node-checks" class="tab-section">
<div role="tabpanel">
{{#if (gt item.NodeChecks.length 0) }}
<HealthcheckList @items={{item.NodeChecks}} />
{{else}}
<p>
This instance has no node health checks.
</p>
{{/if}}
</div>
</div>

View File

@ -1,11 +0,0 @@
<div id="service-checks" class="tab-section">
<div role="tabpanel">
{{#if (gt item.ServiceChecks.length 0) }}
<HealthcheckList @items={{item.ServiceChecks}} @exposed={{proxy.ServiceProxy.Expose.Checks}} />
{{else}}
<p>
This instance has no service health checks.
</p>
{{/if}}
</div>
</div>

View File

@ -23,9 +23,9 @@ Feature: dc / services / instances / gateway: Show Gateway Service Instance
node: node-0
id: gateway-with-id
---
Then the url should be /dc1/services/gateway/instances/node-0/gateway-with-id/service-checks
Then the url should be /dc1/services/gateway/instances/node-0/gateway-with-id/health-checks
And I see serviceChecksIsSelected on the tabs
And I see healthChecksIsSelected on the tabs
When I click addresses on the tabs
And I see addressesIsSelected on the tabs

View File

@ -1,176 +0,0 @@
@setupApplicationTest
Feature: dc / services / instances / proxy: Show Proxy Service Instance
@onlyNamespaceable
Scenario: A Proxy Service instance with a namespace
Given 1 datacenter model with the value "dc1"
And 1 instance model from yaml
---
- Service:
Kind: connect-proxy
Name: service-0-proxy
ID: service-0-proxy-with-id
Proxy:
DestinationServiceName: service-0
Expose:
Checks: false
Paths: []
Upstreams:
- DestinationType: service
DestinationName: service-1
DestinationNamespace: default
LocalBindAddress: 127.0.0.1
LocalBindPort: 1111
- DestinationType: prepared_query
DestinationName: service-group
LocalBindAddress: 127.0.0.1
LocalBindPort: 1112
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0-proxy
node: node-0
id: service-0-proxy-with-id
---
When I click upstreams on the tabs
And I see upstreamsIsSelected on the tabs
And I see 2 of the upstreams object
And I see name on the upstreams like yaml
---
- service-1 default
- service-group
---
@notNamespaceable
Scenario: A Proxy Service instance with no exposed checks
Given 1 datacenter model with the value "dc1"
And 1 instance model from yaml
---
- Service:
Kind: connect-proxy
Name: service-0-proxy
ID: service-0-proxy-with-id
Proxy:
DestinationServiceName: service-0
Expose:
Checks: false
Paths: []
Upstreams:
- DestinationType: service
DestinationName: service-1
DestinationNamespace: default
LocalBindAddress: 127.0.0.1
LocalBindPort: 1111
- DestinationType: prepared_query
DestinationName: service-group
LocalBindAddress: 127.0.0.1
LocalBindPort: 1112
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0-proxy
node: node-0
id: service-0-proxy-with-id
---
Then the url should be /dc1/services/service-0-proxy/instances/node-0/service-0-proxy-with-id/service-checks
And I see destination on the proxy like "service"
And I see serviceChecksIsSelected on the tabs
When I click serviceChecks on the tabs
And I don't see exposed on the serviceChecks
When I click upstreams on the tabs
And I see upstreamsIsSelected on the tabs
And I see 2 of the upstreams object
And I see name on the upstreams like yaml
---
- service-1
- service-group
---
And I see type on the upstreams like yaml
---
- service
- prepared_query
---
And I don't see exposedPaths on the tabs
Scenario: A Proxy Service instance with no automatically exposed checks but with paths
Given 1 datacenter model with the value "dc1"
And 1 instance model from yaml
---
- Service:
Kind: connect-proxy
Name: service-0-proxy
ID: service-0-proxy-with-id
Address: 10.0.0.1
Proxy:
DestinationServiceName: service-0
Expose:
Paths:
- Path: /grpc-metrics
Protocol: grpc
LocalPathPort: 8081
ListenerPort: 8080
- Path: /http-metrics
Protocol: http
LocalPathPort: 8082
ListenerPort: 8083
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0-proxy
node: node-0
id: service-0-proxy-with-id
---
Then the url should be /dc1/services/service-0-proxy/instances/node-0/service-0-proxy-with-id/service-checks
And I see serviceChecksIsSelected on the tabs
When I click serviceChecks on the tabs
And I don't see exposed on the serviceChecks
When I click exposedPaths on the tabs
And I see exposedPaths on the tabs
And I see 2 of the exposedPaths object
And I see combinedAddress on the exposedPaths like yaml
---
- 10.0.0.1:8080/grpc-metrics
- 10.0.0.1:8083/http-metrics
---
Scenario: A Proxy Service instance with only automatically exposed checks but no paths
Given 1 datacenter model with the value "dc1"
And 1 instance model from yaml
---
- Service:
Kind: connect-proxy
Name: service-0-proxy
ID: service-0-proxy-with-id
Address: 10.0.0.1
Proxy:
DestinationServiceName: service-0
Expose:
Checks: true
Paths: []
Checks:
- Name: http-check
Type: http
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0-proxy
node: node-0
id: service-0-proxy-with-id
---
Then the url should be /dc1/services/service-0-proxy/instances/node-0/service-0-proxy-with-id/service-checks
And I see serviceChecksIsSelected on the tabs
And I don't see exposedPaths on the tabs
When I click serviceChecks on the tabs
And I don't see exposed on the serviceChecks
When I click nodeChecks on the tabs
And I don't see exposed on the nodeChecks

View File

@ -47,12 +47,6 @@ Feature: dc / services / instances / show: Show Service Instance
Status: critical
---
Scenario: A Service instance has no Proxy
Given 1 proxy model from yaml
---
- ServiceProxy:
DestinationServiceName: service-1
DestinationServiceID: ~
---
When I visit the instance page for yaml
---
dc: dc1
@ -60,16 +54,12 @@ Feature: dc / services / instances / show: Show Service Instance
node: another-node
id: service-0-with-id
---
Then the url should be /dc1/services/service-0/instances/another-node/service-0-with-id/service-checks
Then I don't see type on the proxy
Then the url should be /dc1/services/service-0/instances/another-node/service-0-with-id/health-checks
Then I see externalSource like "nomad"
And I don't see upstreams on the tabs
And I see serviceChecksIsSelected on the tabs
And I see healthChecksIsSelected on the tabs
And I see 3 of the serviceChecks object
When I click nodeChecks on the tabs
And I see nodeChecksIsSelected on the tabs
And I see 3 of the nodeChecks object
When I click tags on the tabs
@ -98,67 +88,6 @@ Feature: dc / services / instances / show: Show Service Instance
node: node-0
id: service-0-with-id
---
Then the url should be /dc1/services/service-0/instances/node-0/service-0-with-id/service-checks
Then the url should be /dc1/services/service-0/instances/node-0/service-0-with-id/health-checks
And an external edit results in 0 instance models
And pause until I see the text "deregistered" in "[data-notification]"
Scenario: A Service instance with a Proxy with only automatically exposed checks but no paths
Given 1 proxy model from yaml
---
- ServiceProxy:
DestinationServiceName: service-0
DestinationServiceID: ~
Expose:
Checks: true
Paths: []
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0
node: another-node
id: service-0-with-id
---
Then the url should be /dc1/services/service-0/instances/another-node/service-0-with-id/service-checks
And I see serviceChecksIsSelected on the tabs
And I don't see exposedPaths on the tabs
When I click serviceChecks on the tabs
And I see exposed on the serviceChecks
When I click nodeChecks on the tabs
And I don't see exposed on the nodeChecks
Scenario: A Service Instance with a Proxy with no automatically exposed checks
Given 1 proxy model from yaml
---
- ServiceProxy:
DestinationServiceName: service-0
DestinationServiceID: ~
Expose:
Checks: false
Paths: []
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0
node: another-node
id: service-0-with-id
---
Then the url should be /dc1/services/service-0/instances/another-node/service-0-with-id/service-checks
And I see serviceChecksIsSelected on the tabs
And I don't see exposedPaths on the tabs
When I click serviceChecks on the tabs
And I don't see exposed on the serviceChecks
When I click nodeChecks on the tabs
And I don't see exposed on the nodeChecks
@ignore
Scenario: A Service Instance's proxy blocking query is closed when the instance is deregistered
Then ok

View File

@ -1,30 +0,0 @@
@setupApplicationTest
Feature: dc / services / instances / sidecar-proxy: Show Sidecar Proxy Service Instance
Scenario: A Sidecar Proxy Service instance
Given 1 datacenter model with the value "dc1"
And 1 service model from yaml
---
- Service:
Kind: connect-proxy
Name: service-0-sidecar-proxy
ID: service-0-sidecar-proxy-with-id
Proxy:
DestinationServiceName: service-0
DestinationServiceID: service-0-with-id
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0-sidecar-proxy
node: node-0
id: service-0-sidecar-proxy-with-id
---
Then the url should be /dc1/services/service-0-sidecar-proxy/instances/node-0/service-0-sidecar-proxy-with-id/service-checks
And I see destination on the proxy like "instance"
And I see serviceChecksIsSelected on the tabs
When I click upstreams on the tabs
And I see upstreamsIsSelected on the tabs

View File

@ -1,21 +0,0 @@
@setupApplicationTest
Feature: dc / services / instances / with-proxy: Show Service Instance with a proxy
Scenario: A Service instance has a Proxy (no DestinationServiceID)
Given 1 datacenter model with the value "dc1"
And 1 proxy model from yaml
---
- ServiceProxy:
DestinationServiceID: ~
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0
node: node-0
id: service-0-with-id
---
Then the url should be /dc1/services/service-0/instances/node-0/service-0-with-id/service-checks
And I see type on the proxy like "proxy"
And I see serviceChecksIsSelected on the tabs
And I don't see upstreams on the tabs

View File

@ -1,42 +0,0 @@
@setupApplicationTest
Feature: dc / services / instances / with-sidecar: Show Service Instance with a Sidecar Proxy
Scenario: A Service instance has a Sidecar Proxy (a DestinationServiceID)
Given 1 datacenter model with the value "dc1"
And 1 proxy model from yaml
---
- Node: node-0
ServiceProxy:
DestinationServiceID: service-0-with-id
DestinationServiceName: ~
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0
node: node-0
id: service-0-with-id
---
Then the url should be /dc1/services/service-0/instances/node-0/service-0-with-id/service-checks
And I see type on the proxy like "sidecar-proxy"
And I see serviceChecksIsSelected on the tabs
And I don't see upstreams on the tabs
Scenario: A Service instance has no Sidecar Proxy (a DestinationServiceID) on the same node
Given 1 datacenter model with the value "dc1"
And 1 proxy model from yaml
---
- Node: node-1
ServiceProxy:
DestinationServiceID: service-0-with-id
DestinationServiceName: ~
---
When I visit the instance page for yaml
---
dc: dc1
service: service-0
node: node-0
id: service-0-with-id
---
Then the url should be /dc1/services/service-0/instances/node-0/service-0-with-id/service-checks
Then I don't see type on the proxy

View File

@ -1,20 +1,21 @@
export default function(visitable, attribute, collection, text, tabs) {
return {
visit: visitable('/:dc/services/:service/instances/:node/:id'),
externalSource: attribute('data-test-external-source', 'h1 span'),
externalSource: attribute('data-test-external-source', '[data-test-external-source]', {
scope: '.title-bar',
}),
tabs: tabs('tab', [
'service-checks',
'node-checks',
'health-checks',
'addresses',
'upstreams',
'exposed-paths',
'tags',
'meta-data',
]),
serviceChecks: collection('#service-checks [data-test-healthchecks] li', {
serviceChecks: collection('[data-test-service-checks] li', {
exposed: attribute('data-test-exposed', '[data-test-exposed]'),
}),
nodeChecks: collection('#node-checks [data-test-healthchecks] li', {
nodeChecks: collection('[data-test-node-checks] li', {
exposed: attribute('data-test-exposed', '[data-test-exposed]'),
}),
upstreams: collection('#upstreams [data-test-tabular-row]', {
@ -30,9 +31,5 @@ export default function(visitable, attribute, collection, text, tabs) {
address: text('[data-test-address]'),
}),
metaData: collection('#meta-data [data-test-tabular-row]', {}),
proxy: {
type: attribute('data-test-proxy-type', '[data-test-proxy-type]'),
destination: attribute('data-test-proxy-destination', '[data-test-proxy-destination]'),
},
};
}