NET-5414: sameness group service show (#19586)

Fix viewing peered services on different namespaces
This commit is contained in:
Tyler Wendlandt 2023-11-09 15:25:01 -07:00 committed by GitHub
parent cb86b29e89
commit 7699fb12eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 146 additions and 113 deletions

3
.changelog/19586.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
ui: fix being able to view peered services from non-default namnespaces
```

View File

@ -4,7 +4,6 @@
}}
{{#let @list (env "CONSUL_HCP_URL") as |SNL hcpUrl|}}
{{log hcpUrl}}
{{#if (and SNL hcpUrl)}}
<SNL.BackLink
@text={{t "components.hashicorp-consul.side-nav.hcp"}}

View File

@ -17,37 +17,34 @@
(is-href "dc.nspaces" @dc.Name)
as |SNL nspace isManaging|
}}
<SNL.Title class="consul-side-nav__selector-title">{{t "components.hashicorp-consul.side-nav.nspaces.title"}}</SNL.Title>
<SNL.Title class="consul-side-nav__selector-title">{{t
"components.hashicorp-consul.side-nav.nspaces.title"
}}</SNL.Title>
<NavSelector
@list={{@list}}
@items={{sort-by "Name:asc" (reject-by "DeletedAt" @nspaces)}}
@item={{nspace}}
@key="Name"
@icon="folder"
@placeholder={{t "components.hashicorp-consul.side-nav.nspaces.placeholder"}}
@placeholder={{t
"components.hashicorp-consul.side-nav.nspaces.placeholder"
}}
@footerLink={{href-to "dc.nspaces" @dc.Name}}
@footerLinkText={{t "components.hashicorp-consul.side-nav.nspaces.footer"}}
@footerLinkText={{t
"components.hashicorp-consul.side-nav.nspaces.footer"
}}
data-test-nspace-menu
as |Dropdown item|
>
<Dropdown.Checkmark
@selected={{eq nspace.Name item.Name}}
@href={{if
isManaging
(href-to
"dc.services.index"
params=(hash
partition=(if (gt @partition.length 0) @partition undefined)
nspace=item.Name
dc=@dc.Name
)
)
(href-to
"."
params=(hash
partition=(if (gt @partition.length 0) @partition undefined)
nspace=item.Name
)
@href={{href-to
"dc.services.index"
params=(hash
partition=(if (gt @partition.length 0) @partition undefined)
nspace=item.Name
peer=undefined
dc=@dc.Name
)
}}
@isHrefExternal={{false}}

View File

@ -14,16 +14,22 @@
@src={{uri "/*/*/${dc}/partitions" (hash dc=@dc.Name)}}
@onchange={{fn (optional @onchange)}}
/>
<SNL.Title class="consul-side-nav__selector-title">{{t "components.hashicorp-consul.side-nav.partitions.title"}}</SNL.Title>
<SNL.Title class="consul-side-nav__selector-title">{{t
"components.hashicorp-consul.side-nav.partitions.title"
}}</SNL.Title>
<NavSelector
@list={{@list}}
@items={{sort-by "Name:asc" (reject-by "DeletedAt" @partitions)}}
@item={{partition}}
@key="Name"
@icon="users"
@placeholder={{t "components.hashicorp-consul.side-nav.partitions.placeholder"}}
@placeholder={{t
"components.hashicorp-consul.side-nav.partitions.placeholder"
}}
@footerLink={{href-to "dc.partitions" @dc.Name}}
@footerLinkText={{t "components.hashicorp-consul.side-nav.partitions.footer"}}
@footerLinkText={{t
"components.hashicorp-consul.side-nav.partitions.footer"
}}
@disabled={{not canChoose}}
data-test-datacenter-disclosure-menu
as |Dropdown item|
@ -34,13 +40,9 @@
@href={{if
item.href
item.href
(if
isManaging
(href-to
"dc.services.index"
params=(hash partition=item.Name nspace=undefined dc=@dc.Name)
)
(href-to "." params=(hash partition=item.Name nspace=undefined))
(href-to
"dc.services.index"
params=(hash partition=item.Name nspace=undefined peer=undefined dc=@dc.Name)
)
}}
@isHrefExternal={{false}}

View File

@ -83,6 +83,7 @@
<Consul::Service::List
@items={{collection.items}}
@partition={{partition}}
@nspace={{nspace}}
@isPeerDetail={{true}}
/>
</collection.Collection>

View File

@ -10,85 +10,5 @@
@linkable='linkable service'
as |item index|
>
<BlockSlot @name='header'>
<dl class={{item.MeshStatus}}>
<dt>
Health
</dt>
<dd {{tooltip item.healthTooltipText}}></dd>
</dl>
{{#if (gt item.InstanceCount 0)}}
<a
data-test-service-name
href={{href-to
'dc.services.show.index'
item.Name
params=(if
(not-eq item.Partition @partition)
(hash partition=item.Partition nspace=item.Namespace peer=item.PeerName)
(hash peer=item.PeerName)
)
}}
>
{{item.Name}}
</a>
{{else}}
<p data-test-service-name>
{{item.Name}}
</p>
{{/if}}
</BlockSlot>
<BlockSlot @name='details'>
<Consul::Kind @item={{item}} />
<Consul::ExternalSource @item={{item}} />
{{#if
(and
(not-eq item.InstanceCount 0)
(and (not-eq item.Kind 'terminating-gateway') (not-eq item.Kind 'ingress-gateway'))
)
}}
<span>
{{format-number item.InstanceCount}}
{{pluralize item.InstanceCount 'instance' without-count=true}}
</span>
{{/if}}
{{! we are displaying imported-services - don't show bucket-list }}
{{#unless @isPeerDetail}}
<Consul::Bucket::List @item={{item}} @nspace={{@nspace}} @partition={{@partition}} />
{{/unless}}
{{#if (eq item.Kind 'terminating-gateway')}}
<span data-test-associated-service-count>
{{format-number item.GatewayConfig.AssociatedServiceCount}}
{{pluralize item.GatewayConfig.AssociatedServiceCount 'linked service' without-count=true}}
</span>
{{else if (eq item.Kind 'ingress-gateway')}}
<span data-test-associated-service-count>
{{format-number item.GatewayConfig.AssociatedServiceCount}}
{{pluralize item.GatewayConfig.AssociatedServiceCount 'upstream' without-count=true}}
</span>
{{/if}}
{{#if (or item.ConnectedWithGateway item.ConnectedWithProxy)}}
<dl class='mesh'>
<dt>
<Tooltip>
This service uses a proxy for the Consul service mesh
</Tooltip>
</dt>
{{#if (and item.ConnectedWithGateway item.ConnectedWithProxy)}}
<dd data-test-mesh>
in service mesh with proxy and gateway
</dd>
{{else if item.ConnectedWithProxy}}
<dd data-test-mesh>
in service mesh with proxy
</dd>
{{else if item.ConnectedWithGateway}}
<dd data-test-mesh>
in service mesh with gateway
</dd>
{{/if}}
</dl>
{{/if}}
<TagList @item={{item}} />
</BlockSlot>
<Consul::Service::List::Item @item={{item}} @partition={{@partition}} @nspace={{@nspace}} />
</ListCollection>

View File

@ -0,0 +1,82 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
<BlockSlot @name='header'>
<dl class={{@item.MeshStatus}}>
<dt>
Health
</dt>
<dd {{tooltip @item.healthTooltipText}}></dd>
</dl>
{{#if (gt @item.InstanceCount 0)}}
<a
data-test-service-name
href={{href-to
'dc.services.show.index'
@item.Name
params=this.linkParams
}}
>
{{@item.Name}}
</a>
{{else}}
<p data-test-service-name>
{{@item.Name}}
</p>
{{/if}}
</BlockSlot>
<BlockSlot @name='details'>
<Consul::Kind @item={{@item}} />
<Consul::ExternalSource @item={{@item}} />
{{#if
(and
(not-eq @item.InstanceCount 0)
(and (not-eq @item.Kind 'terminating-gateway') (not-eq @item.Kind 'ingress-gateway'))
)
}}
<span>
{{format-number @item.InstanceCount}}
{{pluralize @item.InstanceCount 'instance' without-count=true}}
</span>
{{/if}}
{{! we are displaying imported-services - don't show bucket-list }}
{{#unless @isPeerDetail}}
<Consul::Bucket::List @item={{@item}} @nspace={{@nspace}} @partition={{@partition}} />
{{/unless}}
{{#if (eq @item.Kind 'terminating-gateway')}}
<span data-test-associated-service-count>
{{format-number @item.GatewayConfig.AssociatedServiceCount}}
{{pluralize @item.GatewayConfig.AssociatedServiceCount 'linked service' without-count=true}}
</span>
{{else if (eq @item.Kind 'ingress-gateway')}}
<span data-test-associated-service-count>
{{format-number @item.GatewayConfig.AssociatedServiceCount}}
{{pluralize @item.GatewayConfig.AssociatedServiceCount 'upstream' without-count=true}}
</span>
{{/if}}
{{#if (or @item.ConnectedWithGateway @item.ConnectedWithProxy)}}
<dl class='mesh'>
<dt>
<Tooltip>
This service uses a proxy for the Consul service mesh
</Tooltip>
</dt>
{{#if (and @item.ConnectedWithGateway @item.ConnectedWithProxy)}}
<dd data-test-mesh>
in service mesh with proxy and gateway
</dd>
{{else if @item.ConnectedWithProxy}}
<dd data-test-mesh>
in service mesh with proxy
</dd>
{{else if @item.ConnectedWithGateway}}
<dd data-test-mesh>
in service mesh with gateway
</dd>
{{/if}}
</dl>
{{/if}}
<TagList @item={{@item}} />
</BlockSlot>

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import Component from '@glimmer/component';
export default class ConsulServiceListItem extends Component {
get linkParams() {
const hash = {};
if (this.args.item.Partition && this.args.partition !== this.args.item.Partition) {
hash.partition = this.args.item.Partition;
hash.nspace = this.args.Namespace;
} else if (this.args.item.Namespace && this.args.nspace !== this.args.item.Namespace) {
hash.nspace = this.args.item.Namespace;
}
if (this.args.item.PeerName) {
hash.peer = this.args.item.PeerName;
}
return hash;
}
}

View File

@ -149,7 +149,10 @@ export default class FSMWithOptionalLocation {
url = this.getURLFrom(url)
.split('/')
.filter((item, i) => {
if (i < 3) {
// the max optional parameters we have is 3 (partition, namespace, peer). When we split the path
// by '/' it has a prefixed empty '' in the array. So we know we only have to check up to the 4th
// index for optional parameters.
if (i < 4) {
let found = false;
Object.entries(OPTIONAL).reduce((prev, [key, re]) => {
const res = re.exec(item);

View File

@ -101,6 +101,7 @@ as |sort filters items partition nspace|}}
<Consul::Service::List
@items={{collection.items}}
@partition={{partition}}
@nspace={{nspace}}
>
</Consul::Service::List>
</collection.Collection>