mirror of https://github.com/hashicorp/consul
ui: Create Upstreams tab for Ingress Gateways (#7865)
parent
2adfb42bde
commit
6367160c93
|
@ -22,6 +22,9 @@ export const routes = {
|
||||||
services: {
|
services: {
|
||||||
_options: { path: '/services' },
|
_options: { path: '/services' },
|
||||||
},
|
},
|
||||||
|
upstreams: {
|
||||||
|
_options: { path: '/upstreams' },
|
||||||
|
},
|
||||||
routing: {
|
routing: {
|
||||||
_options: { path: '/routing' },
|
_options: { path: '/routing' },
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
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);
|
||||||
|
},
|
||||||
|
});
|
|
@ -33,3 +33,12 @@
|
||||||
%composite-row-detail .port button:hover {
|
%composite-row-detail .port button:hover {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
%composite-row-detail .feedback-dialog-out {
|
||||||
|
left: -12px;
|
||||||
|
bottom: 12px;
|
||||||
|
}
|
||||||
|
%composite-row-detail .feedback-dialog-out::after {
|
||||||
|
left: 18px;
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
%composite-row {
|
%composite-row {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
border-top-color: $gray-200;
|
border-top-color: $transparent;
|
||||||
border-bottom-color: transparent;
|
border-bottom-color: $gray-200;
|
||||||
border-right-color: transparent;
|
border-right-color: $transparent;
|
||||||
border-left-color: transparent;
|
border-left-color: $transparent;
|
||||||
}
|
}
|
||||||
%composite-row-intent {
|
%composite-row-intent {
|
||||||
border-color: $gray-200;
|
border-color: $gray-200;
|
||||||
|
@ -16,9 +16,6 @@
|
||||||
%composite-row-detail {
|
%composite-row-detail {
|
||||||
color: $gray-500;
|
color: $gray-500;
|
||||||
}
|
}
|
||||||
%composite-row:last-child {
|
|
||||||
border-bottom-color: $gray-200;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Health Checks
|
// Health Checks
|
||||||
%composite-row .passing::before {
|
%composite-row .passing::before {
|
||||||
|
|
|
@ -1,7 +1,19 @@
|
||||||
.list-collection {
|
.list-collection {
|
||||||
|
@extend %list-collection;
|
||||||
height: 500px;
|
height: 500px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.list-collection > ul {
|
%list-collection > ul {
|
||||||
|
border-top: 1px solid $gray-200;
|
||||||
overflow-x: hidden !important;
|
overflow-x: hidden !important;
|
||||||
}
|
}
|
||||||
|
%list-collection > ul > li:nth-child(2) .with-feedback p {
|
||||||
|
bottom: auto;
|
||||||
|
top: 24px;
|
||||||
|
}
|
||||||
|
%list-collection > ul > li:nth-child(2) p::after {
|
||||||
|
bottom: auto;
|
||||||
|
top: -10px !important;
|
||||||
|
border-bottom-width: 18px;
|
||||||
|
border-top-width: 0;
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
// Services - Linked Services tab
|
// Services - Linked Services tab
|
||||||
.gateway-services-list > ul {
|
// TODO - move this into composite-row
|
||||||
@extend %gateway-services-list;
|
.consul-gateway-services-list > ul {
|
||||||
|
@extend %consul-gateway-services-list;
|
||||||
}
|
}
|
||||||
%gateway-services-list > li:not(:first-child) {
|
%consul-gateway-services-list > li:not(:first-child) {
|
||||||
@extend %gateway-service-row;
|
@extend %gateway-service-row;
|
||||||
}
|
}
|
||||||
%gateway-service-row {
|
%gateway-service-row {
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
// Service Detail - Proxy Info tab
|
// Service Detail - Proxy Info tab
|
||||||
.proxy-upstreams > ul {
|
.proxy-upstreams > ul {
|
||||||
@extend %proxy-upstreams-list;
|
@extend %proxy-upstreams-list;
|
||||||
|
border-top: 1px solid $gray-200;
|
||||||
}
|
}
|
||||||
%proxy-upstreams-list > li {
|
%proxy-upstreams-list > li {
|
||||||
@extend %composite-row;
|
@extend %composite-row;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<ConsulKind @item={{item.Service}} />
|
<ConsulKind @item={{item.Service}} />
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="nav">
|
<BlockSlot @name="nav">
|
||||||
{{#if (or (not item.Service.Kind) (eq item.Service.Kind 'terminating-gateway'))}}
|
{{#if (not-eq item.Service.Kind 'mesh-gateway')}}
|
||||||
<TabNav @items={{
|
<TabNav @items={{
|
||||||
compact
|
compact
|
||||||
(array
|
(array
|
||||||
|
@ -25,6 +25,9 @@
|
||||||
(if (eq item.Service.Kind 'terminating-gateway')
|
(if (eq item.Service.Kind 'terminating-gateway')
|
||||||
(hash label="Linked Services" href=(href-to "dc.services.show.services") selected=(is-href "dc.services.show.services"))
|
(hash label="Linked Services" href=(href-to "dc.services.show.services") selected=(is-href "dc.services.show.services"))
|
||||||
'')
|
'')
|
||||||
|
(if (eq item.Service.Kind 'ingress-gateway')
|
||||||
|
(hash label="Upstreams" href=(href-to "dc.services.show.upstreams") selected=(is-href "dc.services.show.upstreams"))
|
||||||
|
'')
|
||||||
(if (not item.Service.Kind)
|
(if (not item.Service.Kind)
|
||||||
(hash label="Intentions" href=(href-to "dc.services.show.intentions") selected=(is-href "dc.services.show.intentions"))
|
(hash label="Intentions" href=(href-to "dc.services.show.intentions") selected=(is-href "dc.services.show.intentions"))
|
||||||
'')
|
'')
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
<section>
|
<section>
|
||||||
<p>
|
<p>
|
||||||
The following services may receive traffic from external services through this gateway. Learn more about configuring gateways in our
|
The following services may receive traffic from external services through this gateway. Learn more about configuring gateways in our
|
||||||
<a href={{env 'CONSUL_TERMINATING_GATEWAYS_URL'}} target="_blank">step-by-step guide.</a>
|
<a href="{{env 'CONSUL_DOCS_URL'}}/connect/terminating_gateway.html" target="_blank" rel="noopener noreferrer">step-by-step guide.</a>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<ListCollection @cellHeight={{73}} @items={{gateway.Services}} class="gateway-services-list" as |item index|>
|
<ListCollection @cellHeight={{73}} @items={{gateway.Services}} class="consul-gateway-services-list" as |item index|>
|
||||||
<a data-test-service-name href={{href-to 'dc.services.show' item.Name}} class={{service/health-checks item}}>
|
<a data-test-service-name href={{href-to 'dc.services.show' item.Name}} class={{service/health-checks item}}>
|
||||||
{{item.Name}}
|
{{item.Name}}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<div id="upstreams" class="tab-section">
|
||||||
|
<div role="tabpanel">
|
||||||
|
{{#if (gt gateway.Services.length 0)}}
|
||||||
|
<section>
|
||||||
|
<p>
|
||||||
|
Upstreams are services that may receive traffic from this gateway. Learn more about configuring gateways in our
|
||||||
|
<a href="{{env 'CONSUL_DOCS_URL'}}/connect/ingress_gateway.html" target="_blank" rel="noopener noreferrer">documentation.</a>
|
||||||
|
</p>
|
||||||
|
<ListCollection @cellHeight={{73}} @items={{gateway.Services}} class="consul-gateway-services-list" as |item index|>
|
||||||
|
<a data-test-service-name href={{href-to 'dc.services.show' item.Name}}>
|
||||||
|
{{item.Name}}
|
||||||
|
</a>
|
||||||
|
<ul>
|
||||||
|
{{#if (not-eq item.GatewayConfig.ListenerPort 0)}}
|
||||||
|
<li class="port">
|
||||||
|
<CopyButton
|
||||||
|
@value={{item.GatewayConfig.ListenerPort}}
|
||||||
|
@name="Port"
|
||||||
|
/>
|
||||||
|
<span>:{{item.GatewayConfig.ListenerPort}}</span>
|
||||||
|
</li>
|
||||||
|
{{/if}}
|
||||||
|
</ul>
|
||||||
|
</ListCollection>
|
||||||
|
</section>
|
||||||
|
{{else}}
|
||||||
|
<p>
|
||||||
|
There are no upstreams.
|
||||||
|
</p>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -81,8 +81,6 @@ module.exports = function(environment, $ = process.env) {
|
||||||
CONSUL_DOCS_LEARN_URL: 'https://learn.hashicorp.com',
|
CONSUL_DOCS_LEARN_URL: 'https://learn.hashicorp.com',
|
||||||
CONSUL_DOCS_API_URL: 'https://www.consul.io/api',
|
CONSUL_DOCS_API_URL: 'https://www.consul.io/api',
|
||||||
CONSUL_COPYRIGHT_URL: 'https://www.hashicorp.com',
|
CONSUL_COPYRIGHT_URL: 'https://www.hashicorp.com',
|
||||||
CONSUL_TERMINATING_GATEWAYS_URL: 'https://www.consul.io/docs/connect/terminating_gateway',
|
|
||||||
CONSUL_INGRESS_GATEWAYS_URL: 'https://www.consul.io/docs/connect/ingress_gateway',
|
|
||||||
});
|
});
|
||||||
const isTestLike = ['staging', 'test'].indexOf(environment) > -1;
|
const isTestLike = ['staging', 'test'].indexOf(environment) > -1;
|
||||||
const isDevLike = ['development', 'staging', 'test'].indexOf(environment) > -1;
|
const isDevLike = ['development', 'staging', 'test'].indexOf(environment) > -1;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@setupApplicationTest
|
@setupApplicationTest
|
||||||
Feature: dc / services / gateway
|
Feature: dc / services / show / services
|
||||||
Background:
|
Background:
|
||||||
Given 1 datacenter model with the value "dc1"
|
Given 1 datacenter model with the value "dc1"
|
||||||
And 1 node models
|
And 1 node models
|
||||||
|
@ -29,6 +29,29 @@ Feature: dc / services / gateway
|
||||||
And the title should be "terminating-gateway-1 - Consul"
|
And the title should be "terminating-gateway-1 - Consul"
|
||||||
When I click linkedServices on the tabs
|
When I click linkedServices on the tabs
|
||||||
Then I see 3 service models
|
Then I see 3 service models
|
||||||
|
Scenario: Don't see the Linked Services tab
|
||||||
|
Given 1 datacenter model with the value "dc1"
|
||||||
|
And 1 node models
|
||||||
|
And 1 service model from yaml
|
||||||
|
---
|
||||||
|
- Service:
|
||||||
|
Name: [Name]
|
||||||
|
Kind: [Kind]
|
||||||
|
---
|
||||||
|
When I visit the service page for yaml
|
||||||
|
---
|
||||||
|
dc: dc1
|
||||||
|
service: [Name]
|
||||||
|
---
|
||||||
|
And the title should be "[Name] - Consul"
|
||||||
|
And I don't see linkedServices on the tabs
|
||||||
|
Where:
|
||||||
|
---------------------------------------------
|
||||||
|
| Name | Kind |
|
||||||
|
| service | ~ |
|
||||||
|
| ingress-gateway | ingress-gateway |
|
||||||
|
| mesh-gateway | mesh-gateway |
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
@setupApplicationTest
|
||||||
|
Feature: dc / services / show / upstreams
|
||||||
|
Background:
|
||||||
|
Given 1 datacenter model with the value "dc1"
|
||||||
|
And 1 node models
|
||||||
|
And 1 service model from yaml
|
||||||
|
---
|
||||||
|
- Service:
|
||||||
|
Name: ingress-gateway-1
|
||||||
|
Kind: ingress-gateway
|
||||||
|
---
|
||||||
|
Scenario: Seeing the Upstreams tab
|
||||||
|
When I visit the service page for yaml
|
||||||
|
---
|
||||||
|
dc: dc1
|
||||||
|
service: ingress-gateway-1
|
||||||
|
---
|
||||||
|
And the title should be "ingress-gateway-1 - Consul"
|
||||||
|
And I see upstreams on the tabs
|
||||||
|
When I click upstreams on the tabs
|
||||||
|
And I see upstreamsIsSelected on the tabs
|
||||||
|
Scenario: Seeing the list of Upstreams
|
||||||
|
Given 3 service models from yaml
|
||||||
|
When I visit the service page for yaml
|
||||||
|
---
|
||||||
|
dc: dc1
|
||||||
|
service: ingress-gateway-1
|
||||||
|
---
|
||||||
|
And the title should be "ingress-gateway-1 - Consul"
|
||||||
|
When I click upstreams on the tabs
|
||||||
|
Then I see 3 service models
|
||||||
|
Scenario: Don't see the Upstreams tab
|
||||||
|
Given 1 datacenter model with the value "dc1"
|
||||||
|
And 1 node models
|
||||||
|
And 1 service model from yaml
|
||||||
|
---
|
||||||
|
- Service:
|
||||||
|
Name: [Name]
|
||||||
|
Kind: [Kind]
|
||||||
|
---
|
||||||
|
When I visit the service page for yaml
|
||||||
|
---
|
||||||
|
dc: dc1
|
||||||
|
service: [Name]
|
||||||
|
---
|
||||||
|
And the title should be "[Name] - Consul"
|
||||||
|
And I don't see upstreams on the tabs
|
||||||
|
Where:
|
||||||
|
---------------------------------------------
|
||||||
|
| Name | Kind |
|
||||||
|
| service | ~ |
|
||||||
|
| terminating-gateway | terminating-gateway |
|
||||||
|
| mesh-gateway | mesh-gateway |
|
||||||
|
---------------------------------------------
|
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
|
@ -7,7 +7,14 @@ export default function(visitable, attribute, collection, text, intentions, filt
|
||||||
dashboardAnchor: {
|
dashboardAnchor: {
|
||||||
href: attribute('href', '[data-test-dashboard-anchor]'),
|
href: attribute('href', '[data-test-dashboard-anchor]'),
|
||||||
},
|
},
|
||||||
tabs: tabs('tab', ['instances', 'linked-services', 'intentions', 'routing', 'tags']),
|
tabs: tabs('tab', [
|
||||||
|
'instances',
|
||||||
|
'linked-services',
|
||||||
|
'upstreams',
|
||||||
|
'intentions',
|
||||||
|
'routing',
|
||||||
|
'tags',
|
||||||
|
]),
|
||||||
filter: filter,
|
filter: filter,
|
||||||
|
|
||||||
// TODO: These need to somehow move to subpages
|
// TODO: These need to somehow move to subpages
|
||||||
|
@ -15,7 +22,7 @@ export default function(visitable, attribute, collection, text, intentions, filt
|
||||||
address: text('[data-test-address]'),
|
address: text('[data-test-address]'),
|
||||||
}),
|
}),
|
||||||
intentions: intentions(),
|
intentions: intentions(),
|
||||||
services: collection('.gateway-services-list> ul > li:not(:first-child)', {
|
services: collection('.consul-gateway-services-list> ul > li:not(:first-child)', {
|
||||||
name: text('[data-test-service-name]'),
|
name: text('[data-test-service-name]'),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue