mirror of https://github.com/status-im/consul.git
ui: Serf Health Check warning notice (#10194)
When the Consul serf health check is failing, this means that the health checks registered with the agent may no longer be correct. Therefore we show a notice to the user when we detect that the serf health check is failing both for the health check listing for nodes and for service instances. There were a few little things we fixed up whilst we were here: - We use our @replace decorator to replace an empty Type with serf in the model. - We noticed that ServiceTags can be null, so we replace that with an empty array. - We added docs for both our Notice component and the Consul::HealthCheck::List component. Notice now defaults to @type=info.
This commit is contained in:
parent
a7d96bb546
commit
04bd576179
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:improvement
|
||||||
|
ui: Show a message to explain that health checks may be out of date if the serf health check is in a critical state
|
||||||
|
```
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Consul::HealthCheck::List
|
||||||
|
|
||||||
|
A presentational component for rendering HealthChecks.
|
||||||
|
|
||||||
|
```hbs preview-template
|
||||||
|
<figure>
|
||||||
|
<figcaption>Grab some mock data...</figcaption>
|
||||||
|
|
||||||
|
<DataSource @src="/default/dc-1/node/my-node" as |source|>
|
||||||
|
<figure>
|
||||||
|
<figcaption>but only show a max of 2 items for docs purposes</figcaption>
|
||||||
|
|
||||||
|
<Consul::HealthCheck::List
|
||||||
|
@items={{slice 0 2 source.data.Checks}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</figure>
|
||||||
|
</DataSource>
|
||||||
|
|
||||||
|
</figure>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
| Argument/Attribute | Type | Default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `items` | `array` | | An array of HealthChecks |
|
||||||
|
|
||||||
|
## See
|
||||||
|
|
||||||
|
- [Template Source Code](./index.hbs)
|
||||||
|
|
||||||
|
---
|
|
@ -25,7 +25,7 @@
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Type</dt>
|
<dt>Type</dt>
|
||||||
<dd data-health-check-type>
|
<dd data-health-check-type>
|
||||||
{{or item.Type 'serf'}}
|
{{item.Type}}
|
||||||
{{#if item.Exposed}}
|
{{#if item.Exposed}}
|
||||||
<em
|
<em
|
||||||
data-test-exposed="true"
|
data-test-exposed="true"
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Notice
|
||||||
|
|
||||||
|
Presentational component for informational/warning/error banners/notices.
|
||||||
|
|
||||||
|
|
||||||
|
```hbs preview-template
|
||||||
|
<Notice
|
||||||
|
@type={{this.type}}
|
||||||
|
as |notice|>
|
||||||
|
<notice.Header>
|
||||||
|
<h3>Header</h3>
|
||||||
|
</notice.Header>
|
||||||
|
<notice.Body>
|
||||||
|
<p>
|
||||||
|
Body
|
||||||
|
</p>
|
||||||
|
</notice.Body>
|
||||||
|
<notice.Footer>
|
||||||
|
<p>
|
||||||
|
<a href="">Footer link</a>
|
||||||
|
</p>
|
||||||
|
</notice.Footer>
|
||||||
|
</Notice>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<figcaption>Provide a widget to change the <code>@type</code></figcaption>
|
||||||
|
|
||||||
|
<select
|
||||||
|
onchange={{action (mut this.type) value="target.value"}}
|
||||||
|
>
|
||||||
|
<option>info</option>
|
||||||
|
<option>warning</option>
|
||||||
|
<option>error</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</figure>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
| Argument/Attribute | Type | Default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `type` | `String` | `info` | Type of notice [info\|warning\|error] |
|
||||||
|
|
||||||
|
## See
|
||||||
|
|
||||||
|
- [Template Source Code](./index.hbs)
|
||||||
|
|
||||||
|
---
|
|
@ -1,46 +0,0 @@
|
||||||
import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
|
|
||||||
import { hbs } from 'ember-cli-htmlbars';
|
|
||||||
|
|
||||||
<Meta title="Components/Notice" component="Notice" />
|
|
||||||
|
|
||||||
# Notice
|
|
||||||
|
|
||||||
<Canvas>
|
|
||||||
<Story name="Basic"
|
|
||||||
argTypes={{
|
|
||||||
type: {
|
|
||||||
defaultValue: 'success',
|
|
||||||
control: {
|
|
||||||
type: 'select',
|
|
||||||
options: [
|
|
||||||
'success',
|
|
||||||
'warning',
|
|
||||||
'info',
|
|
||||||
'highlight',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>{(args) => ({
|
|
||||||
template: hbs`<Notice
|
|
||||||
@type={{type}}
|
|
||||||
as |notice|>
|
|
||||||
<notice.Header>
|
|
||||||
<h3>Header</h3>
|
|
||||||
</notice.Header>
|
|
||||||
<notice.Body>
|
|
||||||
<p>
|
|
||||||
Body
|
|
||||||
</p>
|
|
||||||
</notice.Body>
|
|
||||||
<notice.Footer>
|
|
||||||
<p>
|
|
||||||
Footer
|
|
||||||
</p>
|
|
||||||
</notice.Footer>
|
|
||||||
</Notice>`,
|
|
||||||
context: args
|
|
||||||
})}
|
|
||||||
</Story>
|
|
||||||
</Canvas>
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div
|
<div
|
||||||
class="notice {{@type}}"
|
class="notice {{or @type 'info'}}"
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>
|
||||||
{{yield (hash
|
{{yield (hash
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* Simple replacing decorator, with the primary usecase for avoiding null API
|
* Simple replacing decorator, with the primary usecase for avoiding null API
|
||||||
* errors by decorating model attributes: @replace(null, []) @attr() Tags;
|
* errors by decorating model attributes: @replace(null, []) @attr() Tags;
|
||||||
*/
|
*/
|
||||||
const replace = (find, replace) => (target, propertyKey, desc) => {
|
export const replace = (find, replace) => (target, propertyKey, desc) => {
|
||||||
return {
|
return {
|
||||||
get: function() {
|
get: function() {
|
||||||
const value = desc.get.apply(this, arguments);
|
const value = desc.get.apply(this, arguments);
|
||||||
|
|
|
@ -9,7 +9,7 @@ export default {
|
||||||
node: (item, value) => item.Kind === value,
|
node: (item, value) => item.Kind === value,
|
||||||
},
|
},
|
||||||
check: {
|
check: {
|
||||||
serf: (item, value) => item.Type === '',
|
serf: (item, value) => item.Type === value,
|
||||||
script: (item, value) => item.Type === value,
|
script: (item, value) => item.Type === value,
|
||||||
http: (item, value) => item.Type === value,
|
http: (item, value) => item.Type === value,
|
||||||
tcp: (item, value) => item.Type === value,
|
tcp: (item, value) => item.Type === value,
|
||||||
|
|
|
@ -2,27 +2,29 @@ import Fragment from 'ember-data-model-fragments/fragment';
|
||||||
import { array } from 'ember-data-model-fragments/attributes';
|
import { array } from 'ember-data-model-fragments/attributes';
|
||||||
import { attr } from '@ember-data/model';
|
import { attr } from '@ember-data/model';
|
||||||
import { computed } from '@ember/object';
|
import { computed } from '@ember/object';
|
||||||
|
import { replace, nullValue } from 'consul-ui/decorators/replace';
|
||||||
|
|
||||||
export const schema = {
|
export const schema = {
|
||||||
Status: {
|
Status: {
|
||||||
allowedValues: ['passing', 'warning', 'critical'],
|
allowedValues: ['passing', 'warning', 'critical'],
|
||||||
},
|
},
|
||||||
Type: {
|
Type: {
|
||||||
allowedValues: ['', 'script', 'http', 'tcp', 'ttl', 'docker', 'grpc', 'alias'],
|
allowedValues: ['serf', 'script', 'http', 'tcp', 'ttl', 'docker', 'grpc', 'alias'],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class HealthCheck extends Fragment {
|
export default class HealthCheck extends Fragment {
|
||||||
@attr('string') Name;
|
@attr('string') Name;
|
||||||
@attr('string') CheckID;
|
@attr('string') CheckID;
|
||||||
@attr('string') Type;
|
// an empty Type means its the Consul serf Check
|
||||||
|
@replace('', 'serf') @attr('string') Type;
|
||||||
@attr('string') Status;
|
@attr('string') Status;
|
||||||
@attr('string') Notes;
|
@attr('string') Notes;
|
||||||
@attr('string') Output;
|
@attr('string') Output;
|
||||||
@attr('string') ServiceName;
|
@attr('string') ServiceName;
|
||||||
@attr('string') ServiceID;
|
@attr('string') ServiceID;
|
||||||
@attr('string') Node;
|
@attr('string') Node;
|
||||||
@array('string') ServiceTags;
|
@nullValue([]) @array('string') ServiceTags;
|
||||||
@attr() Definition; // {}
|
@attr() Definition; // {}
|
||||||
|
|
||||||
// Exposed is only set correct if this Check is accessed via instance.MeshChecks
|
// Exposed is only set correct if this Check is accessed via instance.MeshChecks
|
||||||
|
|
|
@ -9,5 +9,5 @@ export default {
|
||||||
ID: item => item.Service.ID || '',
|
ID: item => item.Service.ID || '',
|
||||||
Notes: item => item.Notes,
|
Notes: item => item.Notes,
|
||||||
Output: item => item.Output,
|
Output: item => item.Output,
|
||||||
ServiceTags: item => asArray(item.ServiceTags || []),
|
ServiceTags: item => asArray(item.ServiceTags),
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,13 +39,13 @@ html.is-debug body > .brand-loader {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
ol,
|
> ol,
|
||||||
ul {
|
> ul {
|
||||||
list-style-position: outside;
|
list-style-position: outside;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
margin-left: 2rem;
|
margin-left: 2rem;
|
||||||
}
|
}
|
||||||
ul {
|
> ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,11 +74,18 @@ html.is-debug body > .brand-loader {
|
||||||
color: var(--gray-400);
|
color: var(--gray-400);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
figcaption code {
|
||||||
|
@extend %inline-code;
|
||||||
|
}
|
||||||
figure > [type='text'] {
|
figure > [type='text'] {
|
||||||
border: 1px solid var(--gray-999);
|
border: 1px solid var(--gray-999);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
figure > select {
|
||||||
|
border: 1px solid var(--gray-999);
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// &__snippets__tabs__button {
|
// &__snippets__tabs__button {
|
||||||
// display: none;
|
// display: none;
|
||||||
|
|
|
@ -47,6 +47,26 @@ as |route|>
|
||||||
@filter={{filters}}
|
@filter={{filters}}
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#let (find-by "Type" "serf" items) as |serf|}}
|
||||||
|
{{#if (and serf (eq serf.Status "critical"))}}
|
||||||
|
<Notice
|
||||||
|
data-test-critical-serf-notice
|
||||||
|
@type="warning"
|
||||||
|
as |notice|>
|
||||||
|
<notice.Header>
|
||||||
|
<h2>
|
||||||
|
{{t "routes.dc.nodes.show.healthchecks.critical-serf-notice.header"}}
|
||||||
|
</h2>
|
||||||
|
</notice.Header>
|
||||||
|
<notice.Body>
|
||||||
|
{{t
|
||||||
|
"routes.dc.nodes.show.healthchecks.critical-serf-notice.body"
|
||||||
|
htmlSafe=true
|
||||||
|
}}
|
||||||
|
</notice.Body>
|
||||||
|
</Notice>
|
||||||
|
{{/if}}
|
||||||
|
{{/let}}
|
||||||
<DataCollection
|
<DataCollection
|
||||||
@type="health-check"
|
@type="health-check"
|
||||||
@sort={{sort.value}}
|
@sort={{sort.value}}
|
||||||
|
@ -62,9 +82,10 @@ as |route|>
|
||||||
<collection.Empty>
|
<collection.Empty>
|
||||||
<EmptyState>
|
<EmptyState>
|
||||||
<BlockSlot @name="body">
|
<BlockSlot @name="body">
|
||||||
<p>
|
{{t "routes.dc.nodes.show.healthchecks.empty"
|
||||||
This node has no health checks{{#if (gt items.length 0)}} matching that search{{/if}}.
|
items=items.length
|
||||||
</p>
|
htmlSafe=true
|
||||||
|
}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
</collection.Empty>
|
</collection.Empty>
|
||||||
|
|
|
@ -44,6 +44,26 @@ as |route|>
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#let (find-by "Type" "serf" items) as |serf|}}
|
||||||
|
{{#if (and serf (eq serf.Status "critical"))}}
|
||||||
|
<Notice
|
||||||
|
data-test-critical-serf-notice
|
||||||
|
@type="warning"
|
||||||
|
as |notice|>
|
||||||
|
<notice.Header>
|
||||||
|
<h2>
|
||||||
|
{{t "routes.dc.services.instance.healthchecks.critical-serf-notice.header"}}
|
||||||
|
</h2>
|
||||||
|
</notice.Header>
|
||||||
|
<notice.Body>
|
||||||
|
{{t
|
||||||
|
"routes.dc.services.instance.healthchecks.critical-serf-notice.body"
|
||||||
|
htmlSafe=true
|
||||||
|
}}
|
||||||
|
</notice.Body>
|
||||||
|
</Notice>
|
||||||
|
{{/if}}
|
||||||
|
{{/let}}
|
||||||
<DataCollection
|
<DataCollection
|
||||||
@type="health-check"
|
@type="health-check"
|
||||||
@sort={{sort.value}}
|
@sort={{sort.value}}
|
||||||
|
@ -59,9 +79,10 @@ as |route|>
|
||||||
<collection.Empty>
|
<collection.Empty>
|
||||||
<EmptyState>
|
<EmptyState>
|
||||||
<BlockSlot @name="body">
|
<BlockSlot @name="body">
|
||||||
<p>
|
{{t "routes.dc.services.instance.healthchecks.empty"
|
||||||
This instance has no health checks{{#if (gt items.length 0)}} matching that search{{/if}}.
|
items=items.length
|
||||||
</p>
|
htmlSafe=true
|
||||||
|
}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
</collection.Empty>
|
</collection.Empty>
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
Feature: dc / nodes / show: Show node
|
Feature: dc / nodes / show: Show node
|
||||||
Background:
|
Background:
|
||||||
Given 1 datacenter model with the value "dc1"
|
Given 1 datacenter model with the value "dc1"
|
||||||
|
# 2 nodes are required for the RTT tab to be visible
|
||||||
Scenario: Given 2 nodes all the tabs are visible and clickable
|
Scenario: Given 2 nodes all the tabs are visible and clickable
|
||||||
Given 2 node models from yaml
|
Given 2 node models
|
||||||
When I visit the node page for yaml
|
When I visit the node page for yaml
|
||||||
---
|
---
|
||||||
dc: dc1
|
dc: dc1
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
@setupApplicationTest
|
||||||
|
Feature: dc / nodes / show / health-checks
|
||||||
|
Background:
|
||||||
|
Given 1 datacenter model with the value "dc1"
|
||||||
|
Scenario: A failing serf check
|
||||||
|
Given 1 node model from yaml
|
||||||
|
---
|
||||||
|
ID: node-0
|
||||||
|
Checks:
|
||||||
|
- Type: ''
|
||||||
|
Name: Serf Health Status
|
||||||
|
CheckID: serfHealth
|
||||||
|
Status: critical
|
||||||
|
Output: ouch
|
||||||
|
---
|
||||||
|
When I visit the node page for yaml
|
||||||
|
---
|
||||||
|
dc: dc1
|
||||||
|
node: node-0
|
||||||
|
---
|
||||||
|
And I see healthChecksIsSelected on the tabs
|
||||||
|
And I see criticalSerfNotice on the tabs.healthChecksTab
|
||||||
|
Scenario: A passing serf check
|
||||||
|
Given 1 node model from yaml
|
||||||
|
---
|
||||||
|
ID: node-0
|
||||||
|
Checks:
|
||||||
|
- Type: ''
|
||||||
|
Name: Serf Health Status
|
||||||
|
CheckID: serfHealth
|
||||||
|
Status: passing
|
||||||
|
Output: Agent alive and reachable
|
||||||
|
---
|
||||||
|
When I visit the node page for yaml
|
||||||
|
---
|
||||||
|
dc: dc1
|
||||||
|
node: node-0
|
||||||
|
---
|
||||||
|
And I see healthChecksIsSelected on the tabs
|
||||||
|
And I don't see criticalSerfNotice on the tabs.healthChecksTab
|
|
@ -0,0 +1,66 @@
|
||||||
|
@setupApplicationTest
|
||||||
|
Feature: dc / services / instances / health-checks
|
||||||
|
Background:
|
||||||
|
Given 1 datacenter model with the value "dc1"
|
||||||
|
And 1 proxy model from yaml
|
||||||
|
---
|
||||||
|
- ServiceProxy:
|
||||||
|
DestinationServiceName: service-1
|
||||||
|
DestinationServiceID: ~
|
||||||
|
---
|
||||||
|
Scenario: A failing serf check
|
||||||
|
Given 2 instance models from yaml
|
||||||
|
---
|
||||||
|
- Service:
|
||||||
|
ID: service-0-with-id
|
||||||
|
Node:
|
||||||
|
Node: node-0
|
||||||
|
- Service:
|
||||||
|
ID: service-1-with-id
|
||||||
|
Node:
|
||||||
|
Node: another-node
|
||||||
|
Checks:
|
||||||
|
- Type: ''
|
||||||
|
Name: Serf Health Status
|
||||||
|
CheckID: serfHealth
|
||||||
|
Status: critical
|
||||||
|
Output: ouch
|
||||||
|
---
|
||||||
|
When I visit the instance page for yaml
|
||||||
|
---
|
||||||
|
dc: dc1
|
||||||
|
service: service-0
|
||||||
|
node: another-node
|
||||||
|
id: service-1-with-id
|
||||||
|
---
|
||||||
|
Then the url should be /dc1/services/service-0/instances/another-node/service-1-with-id/health-checks
|
||||||
|
And I see healthChecksIsSelected on the tabs
|
||||||
|
And I see criticalSerfNotice on the tabs.healthChecksTab
|
||||||
|
Scenario: A passing serf check
|
||||||
|
Given 2 instance models from yaml
|
||||||
|
---
|
||||||
|
- Service:
|
||||||
|
ID: service-0-with-id
|
||||||
|
Node:
|
||||||
|
Node: node-0
|
||||||
|
- Service:
|
||||||
|
ID: service-1-with-id
|
||||||
|
Node:
|
||||||
|
Node: another-node
|
||||||
|
Checks:
|
||||||
|
- Type: ''
|
||||||
|
Name: Serf Health Status
|
||||||
|
CheckID: serfHealth
|
||||||
|
Status: passing
|
||||||
|
Output: Agent alive and reachable
|
||||||
|
---
|
||||||
|
When I visit the instance page for yaml
|
||||||
|
---
|
||||||
|
dc: dc1
|
||||||
|
service: service-0
|
||||||
|
node: another-node
|
||||||
|
id: service-1-with-id
|
||||||
|
---
|
||||||
|
Then the url should be /dc1/services/service-0/instances/another-node/service-1-with-id/health-checks
|
||||||
|
And I see healthChecksIsSelected on the tabs
|
||||||
|
And I don't see criticalSerfNotice on the tabs.healthChecksTab
|
|
@ -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,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);
|
||||||
|
});
|
||||||
|
}
|
|
@ -164,6 +164,7 @@ export default {
|
||||||
visitable,
|
visitable,
|
||||||
alias,
|
alias,
|
||||||
attribute,
|
attribute,
|
||||||
|
isPresent,
|
||||||
collection,
|
collection,
|
||||||
text,
|
text,
|
||||||
tabgroup,
|
tabgroup,
|
||||||
|
@ -177,7 +178,9 @@ export default {
|
||||||
visitable,
|
visitable,
|
||||||
deletable,
|
deletable,
|
||||||
clickable,
|
clickable,
|
||||||
|
alias,
|
||||||
attribute,
|
attribute,
|
||||||
|
isPresent,
|
||||||
collection,
|
collection,
|
||||||
tabgroup,
|
tabgroup,
|
||||||
text,
|
text,
|
||||||
|
|
|
@ -2,13 +2,15 @@ export default function(
|
||||||
visitable,
|
visitable,
|
||||||
deletable,
|
deletable,
|
||||||
clickable,
|
clickable,
|
||||||
|
alias,
|
||||||
attribute,
|
attribute,
|
||||||
|
present,
|
||||||
collection,
|
collection,
|
||||||
tabs,
|
tabs,
|
||||||
text,
|
text,
|
||||||
healthChecks
|
healthChecks
|
||||||
) {
|
) {
|
||||||
return {
|
const page = {
|
||||||
visit: visitable('/:dc/nodes/:node'),
|
visit: visitable('/:dc/nodes/:node'),
|
||||||
tabs: tabs('tab', [
|
tabs: tabs('tab', [
|
||||||
'health-checks',
|
'health-checks',
|
||||||
|
@ -17,7 +19,7 @@ export default function(
|
||||||
'lock-sessions',
|
'lock-sessions',
|
||||||
'metadata',
|
'metadata',
|
||||||
]),
|
]),
|
||||||
healthChecks: healthChecks(),
|
healthChecks: alias('tabs.healthChecksTab.healthChecks'),
|
||||||
services: collection('.consul-service-instance-list > ul > li:not(:first-child)', {
|
services: collection('.consul-service-instance-list > ul > li:not(:first-child)', {
|
||||||
name: text('[data-test-service-name]'),
|
name: text('[data-test-service-name]'),
|
||||||
port: attribute('data-test-service-port', '[data-test-service-port]'),
|
port: attribute('data-test-service-port', '[data-test-service-port]'),
|
||||||
|
@ -31,4 +33,9 @@ export default function(
|
||||||
}),
|
}),
|
||||||
metadata: collection('.consul-metadata-list [data-test-tabular-row]', {}),
|
metadata: collection('.consul-metadata-list [data-test-tabular-row]', {}),
|
||||||
};
|
};
|
||||||
|
page.tabs.healthChecksTab = {
|
||||||
|
criticalSerfNotice: present('[data-test-critical-serf-notice]'),
|
||||||
|
healthChecks: healthChecks(),
|
||||||
|
};
|
||||||
|
return page;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,14 @@ export default function(
|
||||||
visitable,
|
visitable,
|
||||||
alias,
|
alias,
|
||||||
attribute,
|
attribute,
|
||||||
|
present,
|
||||||
collection,
|
collection,
|
||||||
text,
|
text,
|
||||||
tabs,
|
tabs,
|
||||||
upstreams,
|
upstreams,
|
||||||
healthChecks
|
healthChecks
|
||||||
) {
|
) {
|
||||||
return {
|
const page = {
|
||||||
visit: visitable('/:dc/services/:service/instances/:node/:id'),
|
visit: visitable('/:dc/services/:service/instances/:node/:id'),
|
||||||
externalSource: attribute('data-test-external-source', '[data-test-external-source]', {
|
externalSource: attribute('data-test-external-source', '[data-test-external-source]', {
|
||||||
scope: '.title',
|
scope: '.title',
|
||||||
|
@ -26,4 +27,9 @@ export default function(
|
||||||
}),
|
}),
|
||||||
metadata: collection('.metadata [data-test-tabular-row]', {}),
|
metadata: collection('.metadata [data-test-tabular-row]', {}),
|
||||||
};
|
};
|
||||||
|
page.tabs.healthChecksTab = {
|
||||||
|
criticalSerfNotice: present('[data-test-critical-serf-notice]'),
|
||||||
|
healthChecks: healthChecks(),
|
||||||
|
};
|
||||||
|
return page;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,20 @@
|
||||||
dc:
|
dc:
|
||||||
|
nodes:
|
||||||
|
show:
|
||||||
|
healthchecks:
|
||||||
|
empty: |
|
||||||
|
<p>
|
||||||
|
This node has no health checks{items, select,
|
||||||
|
0 {}
|
||||||
|
other { matching that search}
|
||||||
|
}.
|
||||||
|
</p>
|
||||||
|
critical-serf-notice:
|
||||||
|
header: Failing serf check
|
||||||
|
body: |
|
||||||
|
<p>
|
||||||
|
This node has a failing serf node check. The health statuses shown on this page are the statuses as they were known before the node became unreachable.
|
||||||
|
</p>
|
||||||
services:
|
services:
|
||||||
show:
|
show:
|
||||||
upstreams:
|
upstreams:
|
||||||
|
@ -7,6 +23,20 @@ dc:
|
||||||
Upstreams are services that may receive traffic from this gateway. If you are not using Consul DNS, please make sure your <code>Host:</code> header uses the correct domain name for the gateway to correctly proxy to its upstreams. Learn more about configuring gateways in our <a href="{CONSUL_DOCS_URL}/connect/ingress-gateways" target="_blank" rel="noopener noreferrer">documentation</a>.
|
Upstreams are services that may receive traffic from this gateway. If you are not using Consul DNS, please make sure your <code>Host:</code> header uses the correct domain name for the gateway to correctly proxy to its upstreams. Learn more about configuring gateways in our <a href="{CONSUL_DOCS_URL}/connect/ingress-gateways" target="_blank" rel="noopener noreferrer">documentation</a>.
|
||||||
</p>
|
</p>
|
||||||
instance:
|
instance:
|
||||||
|
healthchecks:
|
||||||
|
empty: |
|
||||||
|
<p>
|
||||||
|
This instance has no health checks{items, select,
|
||||||
|
0 {}
|
||||||
|
other { matching that search}
|
||||||
|
}.
|
||||||
|
</p>
|
||||||
|
critical-serf-notice:
|
||||||
|
header: Failing serf check
|
||||||
|
body: |
|
||||||
|
<p>
|
||||||
|
This instance has a failing serf node check. The health statuses shown on this page are the statuses as they were known before the node became unreachable.
|
||||||
|
</p>
|
||||||
upstreams:
|
upstreams:
|
||||||
tproxy-mode:
|
tproxy-mode:
|
||||||
header: Transparent proxy mode
|
header: Transparent proxy mode
|
||||||
|
|
Loading…
Reference in New Issue