[ui] Adding canary_tags the web UI (#15458)

* Adding canary_tags to anyplace we show service tags

* CSS moved and tabs to spaces
This commit is contained in:
Phil Renaud 2022-12-05 14:50:17 -05:00 committed by GitHub
parent df749ff54a
commit 541ca94576
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 223 additions and 192 deletions

3
.changelog/15458.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
ui: The web UI will now show canary_tags of services anyplace we would normally show tags.
```

View File

@ -1,156 +1,159 @@
<div
class="sidebar has-subnav service-sidebar {{if this.isSideBarOpen "open"}}"
{{on-click-outside
@fns.closeSidebar
capture=true
}}
class="sidebar has-subnav service-sidebar {{if this.isSideBarOpen "open"}}"
{{on-click-outside
@fns.closeSidebar
capture=true
}}
>
{{#if @service}}
{{keyboard-commands this.keyCommands}}
<header class="detail-header">
<h1 class="title">
{{@service.name}}
{{#if (not-eq @service.provider "consul")}}
<span class="aggregate-status">
{{#if (eq this.aggregateStatus 'Unhealthy')}}
<FlightIcon @name="x-square-fill" @color="#c84034" />
Unhealthy
{{else}}
<FlightIcon @name="check-square-fill" @color="#25ba81" />
Healthy
{{/if}}
</span>
{{/if}}
</h1>
<button
data-test-close-service-sidebar
class="button is-borderless"
type="button"
{{on "click" @fns.closeSidebar}}
>
{{x-icon "cancel"}}
</button>
</header>
{{#if @service}}
{{keyboard-commands this.keyCommands}}
<header class="detail-header">
<h1 class="title">
{{@service.name}}
{{#if (not-eq @service.provider "consul")}}
<span class="aggregate-status">
{{#if (eq this.aggregateStatus 'Unhealthy')}}
<FlightIcon @name="x-square-fill" @color="#c84034" />
Unhealthy
{{else}}
<FlightIcon @name="check-square-fill" @color="#25ba81" />
Healthy
{{/if}}
</span>
{{/if}}
</h1>
<button
data-test-close-service-sidebar
class="button is-borderless"
type="button"
{{on "click" @fns.closeSidebar}}
>
{{x-icon "cancel"}}
</button>
</header>
<div class="boxed-section is-small">
<div
class="boxed-section-body inline-definitions"
>
<span class="label">
Service Details
</span>
<div class="boxed-section is-small">
<div
class="boxed-section-body inline-definitions"
>
<span class="label">
Service Details
</span>
<div>
{{#if @service.connect}}
<span class="pair">
<span class="term">
Connect
</span>
<div>
{{#if @service.connect}}
<span class="pair">
<span class="term">
Connect
</span>
<span>True</span>
</span>
{{/if}}
<span class="pair">
<span class="term">
Allocation
</span>
<LinkTo
@route="allocations.allocation"
@model={{@allocation}}
@query={{hash service=""}}
>
{{@allocation.shortId}}
</LinkTo>
</span>
<span class="pair">
<span class="term">
IP Address &amp; Port
</span>
<a
href="http://{{this.address}}"
target="_blank"
rel="noopener noreferrer"
>
{{this.address}}
</a>
</span>
<span class="pair">
<span class="term">
Client
</span>
<Tooltip @text={{@allocation.node.name}}>
<LinkTo
@route="clients.client"
@model={{@allocation.node}}
>
{{@allocation.node.shortId}}
</LinkTo>
</Tooltip>
</span>
{{#if @service.tags.length}}
<span class="pair is-wrappable">
<span class="term">
Tags
</span>
</span>
{{/if}}
<span class="pair">
<span class="term">
Allocation
</span>
<LinkTo
@route="allocations.allocation"
@model={{@allocation}}
@query={{hash service=""}}
>
{{@allocation.shortId}}
</LinkTo>
</span>
<span class="pair">
<span class="term">
IP Address &amp; Port
</span>
<a
href="http://{{this.address}}"
target="_blank"
rel="noopener noreferrer"
>
{{this.address}}
</a>
</span>
<span class="pair">
<span class="term">
Client
</span>
<Tooltip @text={{@allocation.node.name}}>
<LinkTo
@route="clients.client"
@model={{@allocation.node}}
>
{{@allocation.node.shortId}}
</LinkTo>
</Tooltip>
</span>
{{#if @service.tags.length}}
<span class="pair is-wrappable">
<span class="term">
Tags
</span>
{{#each @service.tags as |tag|}}
<span class="tag is-service">{{tag}}</span>
{{/each}}
</span>
{{/if}}
</div>
</div>
</div>
{{#if this.checks.length}}
<ListTable class="health-checks" @source={{this.checks}} as |t|>
<t.head>
<th class="name">
Check Name
</th>
<th class="status">
Status
</th>
<td class="output">
Output
</td>
</t.head>
<t.body as |row|>
<tr data-service-health={{row.model.Status}}>
<td class="name">
<span title={{row.model.Check}}>{{row.model.Check}}</span>
</td>
<td class="status">
<span>
{{#if (eq row.model.Status "success")}}
<FlightIcon @name="check-square-fill" @color="#25ba81" />
Healthy
{{else if (eq row.model.Status "failure")}}
<FlightIcon @name="x-square-fill" @color="#c84034" />
Unhealthy
{{else if (eq row.model.Status "pending")}}
Pending
{{/if}}
</span>
</td>
<td class="service-output">
<code>
{{row.model.Output}}
</code>
</td>
</tr>
<tr class="service-status-indicators">
<td colspan="3">
<div>
{{#each (dedupe-by-property (filter-by "Check" row.model.Check @service.healthChecks) prop="Timestamp") as |check|}}
<ServiceStatusIndicator @check={{check}} />
{{/each}}
</div>
</td>
</tr>
</t.body>
</ListTable>
{{/if}}
{{#if (eq @service.provider "consul")}}
<table class="table is-fixed connect-info">
<tbody>
{{#each @service.canary_tags as |tag|}}
<span class="tag canary is-service">{{tag}}</span>
{{/each}}
</span>
{{/if}}
</div>
</div>
</div>
{{#if this.checks.length}}
<ListTable class="health-checks" @source={{this.checks}} as |t|>
<t.head>
<th class="name">
Check Name
</th>
<th class="status">
Status
</th>
<td class="output">
Output
</td>
</t.head>
<t.body as |row|>
<tr data-service-health={{row.model.Status}}>
<td class="name">
<span title={{row.model.Check}}>{{row.model.Check}}</span>
</td>
<td class="status">
<span>
{{#if (eq row.model.Status "success")}}
<FlightIcon @name="check-square-fill" @color="#25ba81" />
Healthy
{{else if (eq row.model.Status "failure")}}
<FlightIcon @name="x-square-fill" @color="#c84034" />
Unhealthy
{{else if (eq row.model.Status "pending")}}
Pending
{{/if}}
</span>
</td>
<td class="service-output">
<code>
{{row.model.Output}}
</code>
</td>
</tr>
<tr class="service-status-indicators">
<td colspan="3">
<div>
{{#each (dedupe-by-property (filter-by "Check" row.model.Check @service.healthChecks) prop="Timestamp") as |check|}}
<ServiceStatusIndicator @check={{check}} />
{{/each}}
</div>
</td>
</tr>
</t.body>
</ListTable>
{{/if}}
{{#if (eq @service.provider "consul")}}
<table class="table is-fixed connect-info">
<tbody>
{{#if @service.onUpdate}}
<tr>
<td><strong>On Update</strong></td>
@ -169,15 +172,15 @@
</td>
</tr>
{{/if}}
</tbody>
</table>
{{/if}}
{{#if (and (eq @service.provider "consul") this.consulRedirectLink)}}
<div data-test-consul-link-notice class="notification is-info">
<p>
Nomad cannot read health check information from Consul services, but you can <a href={{this.consulRedirectLink}} target="_blank" rel="noopener noreferrer">view this information in your Consul UI</a>.
</p>
</div>
{{/if}}
{{/if}}
</tbody>
</table>
{{/if}}
{{#if (and (eq @service.provider "consul") this.consulRedirectLink)}}
<div data-test-consul-link-notice class="notification is-info">
<p>
Nomad cannot read health check information from Consul services, but you can <a href={{this.consulRedirectLink}} target="_blank" rel="noopener noreferrer">view this information in your Consul UI</a>.
</p>
</div>
{{/if}}
{{/if}}
</div>

View File

@ -9,6 +9,7 @@ export default class Service extends Fragment {
@attr('string') name;
@attr('string') portLabel;
@attr() tags;
@attr() canary_tags;
@attr('string') onUpdate;
@attr('string') provider;
@fragment('consul-connect') connect;

View File

@ -16,6 +16,7 @@ export default class Service extends Model {
@attr('number') port;
@attr('string') serviceName;
@attr() tags;
@attr() canary_tags;
@alias('serviceName') name;

View File

@ -81,4 +81,21 @@
height: 1rem;
width: 1rem;
}
$tagPadding: 0.75em;
&.canary {
overflow: hidden;
&:before {
content: "Canary";
background-color: $blue-light;
color: $black;
line-height: 1.5em;
margin-left: -$tagPadding;
margin-right: $tagPadding;
padding: 0 $tagPadding;
align-self: normal;
}
}
}

View File

@ -324,6 +324,9 @@
{{#each row.model.tags as |tag|}}
<span class="tag is-service">{{tag}}</span>
{{/each}}
{{#each row.model.canary_tags as |tag|}}
<span class="tag canary is-service">{{tag}}</span>
{{/each}}
</td>
<td data-test-service-health class="is-2">
{{#if (eq row.model.provider "nomad")}}

View File

@ -1,48 +1,51 @@
<tr
data-test-service-row
data-test-service-name={{@service.name}}
data-test-num-allocs={{@service.instances.length}}
data-test-service-provider={{@service.provider}}
data-test-service-level={{@service.level}}
{{on "click" (fn this.gotoService @service)}}
class={{if (eq @service.provider "nomad") "is-interactive"}}
data-test-service-row
data-test-service-name={{@service.name}}
data-test-num-allocs={{@service.instances.length}}
data-test-service-provider={{@service.provider}}
data-test-service-level={{@service.level}}
{{on "click" (fn this.gotoService @service)}}
class={{if (eq @service.provider "nomad") "is-interactive"}}
>
<td
{{keyboard-shortcut
enumerated=true
action=(action "gotoService" @service)
}}
>
{{#if (eq @service.provider "nomad")}}
<FlightIcon @name="nomad-color" />
<LinkTo class="is-primary" @route="jobs.job.services.service" @model={{@service}} @query={{hash level=@service.level}}>{{@service.name}}</LinkTo>
{{else}}
<FlightIcon @name="consul-color" />
{{#if (and (eq @service.provider "consul") this.consulRedirectLink)}}
<a class="is-primary" href={{this.consulRedirectLink}} target="_blank" rel="noopener noreferrer">
{{@service.name}}
</a>
{{else}}
{{@service.name}}
{{/if}}
{{keyboard-shortcut
enumerated=true
action=(action "gotoService" @service)
}}
>
{{#if (eq @service.provider "nomad")}}
<FlightIcon @name="nomad-color" />
<LinkTo class="is-primary" @route="jobs.job.services.service" @model={{@service}} @query={{hash level=@service.level}}>{{@service.name}}</LinkTo>
{{else}}
<FlightIcon @name="consul-color" />
{{#if (and (eq @service.provider "consul") this.consulRedirectLink)}}
<a class="is-primary" href={{this.consulRedirectLink}} target="_blank" rel="noopener noreferrer">
{{@service.name}}
</a>
{{else}}
{{@service.name}}
{{/if}}
{{#if @service.connect}}
<FlightIcon @name="mesh" @color="#444444" />
{{/if}}
{{/if}}
{{/if}}
</td>
<td>
{{@service.level}}
</td>
<td>
{{@service.level}}
</td>
<td>
{{#each @service.tags as |tag|}}
<span class="tag">{{tag}}</span>
<span class="tag is-service">{{tag}}</span>
{{/each}}
{{#each @service.canary_tags as |tag|}}
<span class="tag canary is-service">{{tag}}</span>
{{/each}}
</td>
<td>
{{#if (eq @service.provider "nomad")}}
{{@service.instances.length}} {{pluralize "allocation" @service.instances.length}}
{{else}}
--
{{/if}}
</td>
<td>
{{#if (eq @service.provider "nomad")}}
{{@service.instances.length}} {{pluralize "allocation" @service.instances.length}}
{{else}}
--
{{/if}}
</td>
</tr>