diff --git a/ui/packages/consul-ui/app/components/data-collection/index.js b/ui/packages/consul-ui/app/components/data-collection/index.js
index fcde9b9f1..62e0d8220 100644
--- a/ui/packages/consul-ui/app/components/data-collection/index.js
+++ b/ui/packages/consul-ui/app/components/data-collection/index.js
@@ -1,5 +1,6 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
+import { computed } from '@ember/object';
import { sort } from '@ember/object/computed';
import { defineProperty } from '@ember/object';
@@ -12,6 +13,18 @@ export default class DataCollectionComponent extends Component {
return this.args.type;
}
+ @computed('args.items', 'args.items.content')
+ get content() {
+ // TODO: Temporary little hack to ensure we detect DataSource proxy
+ // objects but not any other special Ember Proxy object like ember-data
+ // things. Remove this once we no longer need the Proxies
+ if (this.args.items.dispatchEvent === 'function') {
+ return this.args.items.content;
+ }
+ return this.args.items;
+ }
+
+ @computed('comparator', 'searched')
get items() {
// the ember sort computed accepts either:
// 1. The name of a property (as a string) returning an array properties to sort by
@@ -24,6 +37,7 @@ export default class DataCollectionComponent extends Component {
return this.sorted;
}
+ @computed('type', 'filtered', 'args.filters.searchproperties', 'args.search')
get searched() {
if (typeof this.args.search === 'undefined') {
return this.filtered;
@@ -36,17 +50,19 @@ export default class DataCollectionComponent extends Component {
return this.filtered.filter(predicate(this.args.search, options));
}
+ @computed('type', 'content', 'args.filters')
get filtered() {
if (typeof this.args.filters === 'undefined') {
- return this.args.items;
+ return this.content;
}
const predicate = this.filter.predicate(this.type);
if (typeof predicate === 'undefined') {
- return this.args.items;
+ return this.content;
}
- return this.args.items.filter(predicate(this.args.filters));
+ return this.content.filter(predicate(this.args.filters));
}
+ @computed('type', 'args.sort')
get comparator() {
if (typeof this.args.sort === 'undefined') {
return [];
diff --git a/ui/packages/consul-ui/app/filter/predicates/health-check.js b/ui/packages/consul-ui/app/filter/predicates/health-check.js
new file mode 100644
index 000000000..ae7b32949
--- /dev/null
+++ b/ui/packages/consul-ui/app/filter/predicates/health-check.js
@@ -0,0 +1,21 @@
+export default {
+ statuses: {
+ passing: (item, value) => item.Status === value,
+ warning: (item, value) => item.Status === value,
+ critical: (item, value) => item.Status === value,
+ },
+ kinds: {
+ service: (item, value) => item.Kind === value,
+ node: (item, value) => item.Kind === value,
+ },
+ checks: {
+ serf: (item, value) => item.Type === '',
+ script: (item, value) => item.Type === value,
+ http: (item, value) => item.Type === value,
+ tcp: (item, value) => item.Type === value,
+ ttl: (item, value) => item.Type === value,
+ docker: (item, value) => item.Type === value,
+ grpc: (item, value) => item.Type === value,
+ alias: (item, value) => item.Type === value,
+ },
+};
diff --git a/ui/packages/consul-ui/app/models/health-check.js b/ui/packages/consul-ui/app/models/health-check.js
new file mode 100644
index 000000000..cbbd462f9
--- /dev/null
+++ b/ui/packages/consul-ui/app/models/health-check.js
@@ -0,0 +1,41 @@
+import Fragment from 'ember-data-model-fragments/fragment';
+import { array } from 'ember-data-model-fragments/attributes';
+import { attr } from '@ember-data/model';
+import { computed } from '@ember/object';
+
+export const schema = {
+ Status: {
+ allowedValues: ['passing', 'warning', 'critical'],
+ },
+ Type: {
+ allowedValues: ['', 'script', 'http', 'tcp', 'ttl', 'docker', 'grpc', 'alias'],
+ },
+};
+
+export default class HealthCheck extends Fragment {
+ @attr('string') Name;
+ @attr('string') CheckID;
+ @attr('string') Type;
+ @attr('string') Status;
+ @attr('string') Notes;
+ @attr('string') Output;
+ @attr('string') ServiceName;
+ @attr('string') ServiceID;
+ @attr('string') Node;
+ @array('string') ServiceTags;
+ @attr() Definition; // {}
+
+ // Exposed is only set correct if this Check is accessed via instance.MeshChecks
+ // essentially this is a lazy MeshHealthCheckModel
+ @attr('boolean') Exposed;
+
+ @computed('ServiceID')
+ get Kind() {
+ return this.ServiceID === '' ? 'node' : 'service';
+ }
+
+ @computed('Type')
+ get Exposable() {
+ return ['http', 'grpc'].includes(this.Type);
+ }
+}
diff --git a/ui/packages/consul-ui/app/models/node.js b/ui/packages/consul-ui/app/models/node.js
index 3723743a8..8d2892abd 100644
--- a/ui/packages/consul-ui/app/models/node.js
+++ b/ui/packages/consul-ui/app/models/node.js
@@ -1,5 +1,6 @@
import Model, { attr } from '@ember-data/model';
import { computed } from '@ember/object';
+import { fragmentArray } from 'ember-data-model-fragments/attributes';
export const PRIMARY_KEY = 'uid';
export const SLUG_KEY = 'ID';
@@ -18,7 +19,7 @@ export default class Node extends Model {
@attr() Meta; // {}
@attr() TaggedAddresses; // {lan, wan}
@attr() Services; // ServiceInstances[]
- @attr() Checks; // Checks[]
+ @fragmentArray('health-check') Checks;
@computed('Checks.[]', 'ChecksCritical', 'ChecksPassing', 'ChecksWarning')
get Status() {
diff --git a/ui/packages/consul-ui/app/models/proxy.js b/ui/packages/consul-ui/app/models/proxy.js
index ec8ba6a8b..7508f17c8 100644
--- a/ui/packages/consul-ui/app/models/proxy.js
+++ b/ui/packages/consul-ui/app/models/proxy.js
@@ -1,10 +1,11 @@
import Model, { attr } from '@ember-data/model';
+import ServiceInstanceModel from './service-instance';
export const PRIMARY_KEY = 'uid';
export const SLUG_KEY = 'Node,ServiceID';
// TODO: This should be changed to ProxyInstance
-export default class Proxy extends Model {
+export default class Proxy extends ServiceInstanceModel {
@attr('string') uid;
@attr('string') ID;
diff --git a/ui/packages/consul-ui/app/models/service-instance.js b/ui/packages/consul-ui/app/models/service-instance.js
index 0ee81e204..dd8631068 100644
--- a/ui/packages/consul-ui/app/models/service-instance.js
+++ b/ui/packages/consul-ui/app/models/service-instance.js
@@ -1,5 +1,6 @@
import Model, { attr, belongsTo } from '@ember-data/model';
-import { computed } from '@ember/object';
+import { fragmentArray } from 'ember-data-model-fragments/attributes';
+import { computed, get, set } from '@ember/object';
import { or, filter, alias } from '@ember/object/computed';
export const PRIMARY_KEY = 'uid';
@@ -15,7 +16,7 @@ export default class ServiceInstance extends Model {
@attr() Proxy;
@attr() Node;
@attr() Service;
- @attr() Checks;
+ @fragmentArray('health-check') Checks;
@attr('number') SyncTime;
@attr() meta;
@@ -29,8 +30,35 @@ export default class ServiceInstance extends Model {
@alias('Service.Tags') Tags;
@alias('Service.Meta') Meta;
@alias('Service.Namespace') Namespace;
- @filter('Checks.[]', (item, i, arr) => item.ServiceID !== '') ServiceChecks;
- @filter('Checks.[]', (item, i, arr) => item.ServiceID === '') NodeChecks;
+
+ @filter('Checks.@each.Kind', (item, i, arr) => item.Kind === 'service') ServiceChecks;
+ @filter('Checks.@each.Kind', (item, i, arr) => item.Kind === 'node') NodeChecks;
+
+ // MeshChecks are a concatenation of Checks for the Instance and Checks for
+ // the ProxyInstance. Checks is an ember-data-model-fragment, so we can't just
+ // concat it, we have to loop through all the items in order to merge
+ @computed('Checks', 'ProxyInstance.Checks', 'ProxyInstance.ServiceProxy.Expose.Checks')
+ get MeshChecks() {
+ return (get(this, 'Checks') || [])
+ .map(item => {
+ set(
+ item,
+ 'Exposed',
+ get(this, 'ProxyInstance.ServiceProxy.Expose.Checks') && get(item, 'Exposable')
+ );
+ return item;
+ })
+ .concat(
+ (get(this, 'ProxyInstance.Checks') || []).map(item => {
+ set(
+ item,
+ 'Exposed',
+ get(this, 'ProxyInstance.ServiceProxy.Expose.Checks') && get(item, 'Exposable')
+ );
+ return item;
+ })
+ );
+ }
@computed('Service.Meta')
get ExternalSources() {
diff --git a/ui/packages/consul-ui/app/routes/dc/nodes/show/healthchecks.js b/ui/packages/consul-ui/app/routes/dc/nodes/show/healthchecks.js
index feb40dc04..e77d75c56 100644
--- a/ui/packages/consul-ui/app/routes/dc/nodes/show/healthchecks.js
+++ b/ui/packages/consul-ui/app/routes/dc/nodes/show/healthchecks.js
@@ -1,12 +1,30 @@
import Route from 'consul-ui/routing/route';
export default class HealthchecksRoute extends Route {
+ queryParams = {
+ sortBy: 'sort',
+ status: 'status',
+ kind: 'kind',
+ check: 'check',
+ searchproperty: {
+ as: 'searchproperty',
+ empty: [['Name', 'Service', 'CheckID', 'Notes', 'Output', 'ServiceTags']],
+ },
+ search: {
+ as: 'filter',
+ replace: true,
+ },
+ };
+
model() {
const parent = this.routeName
.split('.')
.slice(0, -1)
.join('.');
- return this.modelFor(parent);
+ return {
+ ...this.modelFor(parent),
+ searchProperties: this.queryParams.searchproperty.empty[0],
+ };
}
setupController(controller, model) {
diff --git a/ui/packages/consul-ui/app/routes/dc/services/instance.js b/ui/packages/consul-ui/app/routes/dc/services/instance.js
index 861a071e8..feea1d16b 100644
--- a/ui/packages/consul-ui/app/routes/dc/services/instance.js
+++ b/ui/packages/consul-ui/app/routes/dc/services/instance.js
@@ -29,7 +29,7 @@ export default class InstanceRoute extends Route {
// the proxy itself is just a normal service model
proxy = await this.data.source(
uri =>
- uri`/${nspace}/${dc}/service-instance/${proxyParams.id}/${proxyParams.node}/${proxyParams.name}`
+ uri`/${nspace}/${dc}/proxy-service-instance/${proxyParams.id}/${proxyParams.node}/${proxyParams.name}`
);
}
}
diff --git a/ui/packages/consul-ui/app/routes/dc/services/instance/healthchecks.js b/ui/packages/consul-ui/app/routes/dc/services/instance/healthchecks.js
index feb40dc04..cf650e9b1 100644
--- a/ui/packages/consul-ui/app/routes/dc/services/instance/healthchecks.js
+++ b/ui/packages/consul-ui/app/routes/dc/services/instance/healthchecks.js
@@ -1,12 +1,30 @@
import Route from 'consul-ui/routing/route';
export default class HealthchecksRoute extends Route {
+ queryParams = {
+ sortBy: 'sort',
+ status: 'status',
+ kind: 'kind',
+ check: 'check',
+ searchproperty: {
+ as: 'searchproperty',
+ empty: [['Name', 'Node', 'CheckID', 'Notes', 'Output', 'ServiceTags']],
+ },
+ search: {
+ as: 'filter',
+ replace: true,
+ },
+ };
+
model() {
const parent = this.routeName
.split('.')
.slice(0, -1)
.join('.');
- return this.modelFor(parent);
+ return {
+ ...this.modelFor(parent),
+ searchProperties: this.queryParams.searchproperty.empty[0],
+ };
}
setupController(controller, model) {
diff --git a/ui/packages/consul-ui/app/search/predicates/health-check.js b/ui/packages/consul-ui/app/search/predicates/health-check.js
new file mode 100644
index 000000000..a74d93445
--- /dev/null
+++ b/ui/packages/consul-ui/app/search/predicates/health-check.js
@@ -0,0 +1,32 @@
+const asArray = function(arr) {
+ return Array.isArray(arr) ? arr : arr.toArray();
+};
+export default {
+ Name: (item, value) => {
+ return item.Name.toLowerCase().indexOf(value.toLowerCase()) !== -1;
+ },
+ Node: (item, value) => {
+ return item.Node.toLowerCase().indexOf(value.toLowerCase()) !== -1;
+ },
+ Service: (item, value) => {
+ const lower = value.toLowerCase();
+ return (
+ item.ServiceName.toLowerCase().indexOf(lower) !== -1 ||
+ item.ServiceID.toLowerCase().indexOf(lower) !== -1
+ );
+ },
+ CheckID: (item, value) => (item.CheckID || '').toLowerCase().indexOf(value.toLowerCase()) !== -1,
+ Notes: (item, value) =>
+ item.Notes.toString()
+ .toLowerCase()
+ .indexOf(value.toLowerCase()) !== -1,
+ Output: (item, value) =>
+ item.Output.toString()
+ .toLowerCase()
+ .indexOf(value.toLowerCase()) !== -1,
+ ServiceTags: (item, value) => {
+ return asArray(item.ServiceTags || []).some(
+ item => item.toLowerCase().indexOf(value.toLowerCase()) !== -1
+ );
+ },
+};
diff --git a/ui/packages/consul-ui/app/services/data-source/protocols/http.js b/ui/packages/consul-ui/app/services/data-source/protocols/http.js
index 3798a5f7d..97493b7b3 100644
--- a/ui/packages/consul-ui/app/services/data-source/protocols/http.js
+++ b/ui/packages/consul-ui/app/services/data-source/protocols/http.js
@@ -26,6 +26,9 @@ export default class HttpService extends Service {
@service('repository/service-instance')
'service-instance';
+ @service('repository/service-instance')
+ 'proxy-service-instance';
+
@service('repository/service-instance')
'service-instances';
@@ -192,6 +195,11 @@ export default class HttpService extends Service {
find = configuration =>
repo.findBySlug(rest[0], rest[1], rest[2], dc, nspace, configuration);
break;
+ case 'proxy-service-instance':
+ // id, node, service
+ find = configuration =>
+ repo.findProxyBySlug(rest[0], rest[1], rest[2], dc, nspace, configuration);
+ break;
case 'proxy-instance':
// id, node, service
find = configuration =>
diff --git a/ui/packages/consul-ui/app/services/filter.js b/ui/packages/consul-ui/app/services/filter.js
index a051c72d1..89b2cf869 100644
--- a/ui/packages/consul-ui/app/services/filter.js
+++ b/ui/packages/consul-ui/app/services/filter.js
@@ -4,6 +4,7 @@ import { andOr } from 'consul-ui/utils/filter';
import acl from 'consul-ui/filter/predicates/acl';
import service from 'consul-ui/filter/predicates/service';
import serviceInstance from 'consul-ui/filter/predicates/service-instance';
+import healthCheck from 'consul-ui/filter/predicates/health-check';
import node from 'consul-ui/filter/predicates/node';
import kv from 'consul-ui/filter/predicates/kv';
import intention from 'consul-ui/filter/predicates/intention';
@@ -14,6 +15,7 @@ const predicates = {
acl: andOr(acl),
service: andOr(service),
['service-instance']: andOr(serviceInstance),
+ ['health-check']: andOr(healthCheck),
node: andOr(node),
kv: andOr(kv),
intention: andOr(intention),
diff --git a/ui/packages/consul-ui/app/services/repository/service-instance.js b/ui/packages/consul-ui/app/services/repository/service-instance.js
index 31ec872f1..3515903cc 100644
--- a/ui/packages/consul-ui/app/services/repository/service-instance.js
+++ b/ui/packages/consul-ui/app/services/repository/service-instance.js
@@ -1,11 +1,15 @@
import RepositoryService from 'consul-ui/services/repository';
+import { inject as service } from '@ember/service';
+import { set, get } from '@ember/object';
+
const modelName = 'service-instance';
export default class ServiceInstanceService extends RepositoryService {
+ @service('repository/proxy') proxyRepo;
getModelName() {
return modelName;
}
- findByService(slug, dc, nspace, configuration = {}) {
+ async findByService(slug, dc, nspace, configuration = {}) {
const query = {
dc: dc,
ns: nspace,
@@ -18,7 +22,7 @@ export default class ServiceInstanceService extends RepositoryService {
return this.store.query(this.getModelName(), query);
}
- findBySlug(serviceId, node, service, dc, nspace, configuration = {}) {
+ async findBySlug(serviceId, node, service, dc, nspace, configuration = {}) {
const query = {
dc: dc,
ns: nspace,
@@ -32,4 +36,27 @@ export default class ServiceInstanceService extends RepositoryService {
}
return this.store.queryRecord(this.getModelName(), query);
}
+
+ async findProxyBySlug(serviceId, node, service, dc, nspace, configuration = {}) {
+ const instance = await this.findBySlug(...arguments);
+ let proxy = this.store.peekRecord('proxy', instance.uid);
+ // if(typeof proxy === 'undefined') {
+ // await proxyRepo.create({})
+ // }
+
+ // Copy over all the things to the ProxyServiceInstance
+ ['Service', 'Node'].forEach(prop => {
+ set(proxy, prop, instance[prop]);
+ });
+ ['Checks'].forEach(prop => {
+ instance[prop].forEach(item => {
+ if (typeof item !== 'undefined') {
+ proxy[prop].addFragment(item.copy());
+ }
+ });
+ });
+ // delete the ServiceInstance record as we now have a ProxyServiceInstance
+ instance.unloadRecord();
+ return proxy;
+ }
}
diff --git a/ui/packages/consul-ui/app/services/search.js b/ui/packages/consul-ui/app/services/search.js
index 09801fe91..f6970d9c8 100644
--- a/ui/packages/consul-ui/app/services/search.js
+++ b/ui/packages/consul-ui/app/services/search.js
@@ -4,6 +4,7 @@ import setHelpers from 'mnemonist/set';
import intention from 'consul-ui/search/predicates/intention';
import upstreamInstance from 'consul-ui/search/predicates/upstream-instance';
import serviceInstance from 'consul-ui/search/predicates/service-instance';
+import healthCheck from 'consul-ui/search/predicates/health-check';
import acl from 'consul-ui/search/predicates/acl';
import service from 'consul-ui/search/predicates/service';
import node from 'consul-ui/search/predicates/node';
@@ -47,6 +48,7 @@ const predicates = {
service: search(service),
['service-instance']: search(serviceInstance),
['upstream-instance']: upstreamInstance(),
+ ['health-check']: search(healthCheck),
node: search(node),
kv: search(kv),
acl: search(acl),
diff --git a/ui/packages/consul-ui/app/services/sort.js b/ui/packages/consul-ui/app/services/sort.js
index cffd1ad4f..dd6399390 100644
--- a/ui/packages/consul-ui/app/services/sort.js
+++ b/ui/packages/consul-ui/app/services/sort.js
@@ -4,7 +4,7 @@ import serviceInstance from 'consul-ui/sort/comparators/service-instance';
import upstreamInstance from 'consul-ui/sort/comparators/upstream-instance';
import acl from 'consul-ui/sort/comparators/acl';
import kv from 'consul-ui/sort/comparators/kv';
-import check from 'consul-ui/sort/comparators/check';
+import healthCheck from 'consul-ui/sort/comparators/health-check';
import intention from 'consul-ui/sort/comparators/intention';
import token from 'consul-ui/sort/comparators/token';
import role from 'consul-ui/sort/comparators/role';
@@ -31,9 +31,9 @@ const comparators = {
service: service(options),
['service-instance']: serviceInstance(options),
['upstream-instance']: upstreamInstance(options),
+ ['health-check']: healthCheck(options),
acl: acl(options),
kv: kv(options),
- check: check(options),
intention: intention(options),
token: token(options),
role: role(options),
diff --git a/ui/packages/consul-ui/app/sort/comparators/check.js b/ui/packages/consul-ui/app/sort/comparators/health-check.js
similarity index 91%
rename from ui/packages/consul-ui/app/sort/comparators/check.js
rename to ui/packages/consul-ui/app/sort/comparators/health-check.js
index c3993a903..be70e9fcf 100644
--- a/ui/packages/consul-ui/app/sort/comparators/check.js
+++ b/ui/packages/consul-ui/app/sort/comparators/health-check.js
@@ -1,4 +1,4 @@
-export default () => key => {
+export default ({ properties }) => (key = 'Status:asc') => {
if (key.startsWith('Status:')) {
return function(itemA, itemB) {
const [, dir] = key.split(':');
@@ -38,5 +38,5 @@ export default () => key => {
return 0;
};
}
- return key;
+ return properties(['Name', 'Kind'])(key);
};
diff --git a/ui/packages/consul-ui/app/sort/comparators/service.js b/ui/packages/consul-ui/app/sort/comparators/service.js
index 22f4029c3..1b06fea92 100644
--- a/ui/packages/consul-ui/app/sort/comparators/service.js
+++ b/ui/packages/consul-ui/app/sort/comparators/service.js
@@ -1,4 +1,4 @@
-export default ({ properties }) => (key = 'Name:asc') => {
+export default ({ properties }) => (key = 'Status:asc') => {
if (key.startsWith('Status:')) {
return function(serviceA, serviceB) {
const [, dir] = key.split(':');
diff --git a/ui/packages/consul-ui/app/styles/layout.scss b/ui/packages/consul-ui/app/styles/layout.scss
index 01a8a0347..46cf52cdb 100644
--- a/ui/packages/consul-ui/app/styles/layout.scss
+++ b/ui/packages/consul-ui/app/styles/layout.scss
@@ -9,7 +9,8 @@ html[data-route$='edit'] .app-view > header + div > *:first-child {
/* if it is a filter bar and the thing after the filter bar is a p then it also */
/* needs a top margun :S */
%app-view-content [role='tabpanel'] > *:first-child:not(.filter-bar):not(table),
-%app-view-content [role='tabpanel'] > .filter-bar + p {
+%app-view-content [role='tabpanel'] > .filter-bar + p,
+%app-view-content [role='tabpanel'] .consul-health-check-list {
margin-top: 1.25em;
}
.consul-upstream-instance-list,
diff --git a/ui/packages/consul-ui/app/templates/dc/nodes/show/healthchecks.hbs b/ui/packages/consul-ui/app/templates/dc/nodes/show/healthchecks.hbs
index 21495928f..48e5cc256 100644
--- a/ui/packages/consul-ui/app/templates/dc/nodes/show/healthchecks.hbs
+++ b/ui/packages/consul-ui/app/templates/dc/nodes/show/healthchecks.hbs
@@ -1,15 +1,58 @@
-
-
- {{#if (gt item.Checks.length 0) }}
-
- {{else}}
-
-
-
- This node has no health checks.
-
-
-
- {{/if}}
-
-
\ No newline at end of file
+{{#let (hash
+ statuses=(if status (split status ',') undefined)
+ kinds=(if kind (split kind ',') undefined)
+ checks=(if check (split check ',') undefined)
+ searchproperties=(if (not-eq searchproperty undefined)
+ (split searchproperty ',')
+ searchProperties
+ )
+) as |filters|}}
+ {{#let (or sortBy "Status:asc") as |sort|}}
+
+
+ {{#if (gt item.Checks.length 0) }}
+
+
+ {{/if}}
+
+
+
+
+
+
+
+
+ This node has no health checks{{#if (gt item.Checks.length 0)}} matching that search{{/if}}.
+
+
+
+
+
+
+
+ {{/let}}
+{{/let}}
\ No newline at end of file
diff --git a/ui/packages/consul-ui/app/templates/dc/services/instance/healthchecks.hbs b/ui/packages/consul-ui/app/templates/dc/services/instance/healthchecks.hbs
index 00ec73080..5b52725ba 100644
--- a/ui/packages/consul-ui/app/templates/dc/services/instance/healthchecks.hbs
+++ b/ui/packages/consul-ui/app/templates/dc/services/instance/healthchecks.hbs
@@ -1,22 +1,60 @@
+{{#let (hash
+ statuses=(if status (split status ',') undefined)
+ kinds=(if kind (split kind ',') undefined)
+ checks=(if check (split check ',') undefined)
+ searchproperties=(if (not-eq searchproperty undefined)
+ (split searchproperty ',')
+ searchProperties
+ )
+) as |filters|}}
+ {{#let (or sortBy "Status:asc") as |sort|}}
- {{#let (append item.Checks (or proxy.Checks (array))) as |checks|}}
- {{#if (gt checks.length 0) }}
-
- {{else}}
-
-
-
- This instance has no health checks.
-
-
-
+
+ {{#if (gt item.MeshChecks.length 0) }}
+
+
{{/if}}
- {{/let}}
+
+
+
+
+
+
+
+
+
+ This instance has no health checks{{#if (gt item.MeshChecks.length 0)}} matching that search{{/if}}.
+
+
+
+
+
+
+ {{/let}}
+{{/let}}
diff --git a/ui/packages/consul-ui/tests/integration/services/repository/node-test.js b/ui/packages/consul-ui/tests/integration/services/repository/node-test.js
index a6cb0f65d..a7a1f5d67 100644
--- a/ui/packages/consul-ui/tests/integration/services/repository/node-test.js
+++ b/ui/packages/consul-ui/tests/integration/services/repository/node-test.js
@@ -28,18 +28,10 @@ test('findByDatacenter returns the correct data for list endpoint', function(ass
return service.findAllByDatacenter(dc);
},
function performAssertion(actual, expected) {
- assert.deepEqual(
- actual,
- expected(function(payload) {
- return payload.map(item =>
- Object.assign({}, item, {
- SyncTime: now,
- Datacenter: dc,
- uid: `["${nspace}","${dc}","${item.ID}"]`,
- })
- );
- })
- );
+ actual.forEach(item => {
+ assert.equal(item.uid, `["${nspace}","${dc}","${item.ID}"]`);
+ assert.equal(item.Datacenter, dc);
+ });
}
);
});
@@ -55,22 +47,8 @@ test('findBySlug returns the correct data for item endpoint', function(assert) {
return service.findBySlug(id, dc);
},
function(actual, expected) {
- assert.deepEqual(
- actual,
- expected(function(payload) {
- const item = payload;
- return Object.assign({}, item, {
- Datacenter: dc,
- uid: `["${nspace}","${dc}","${item.ID}"]`,
- meta: {
- cacheControl: undefined,
- cursor: undefined,
- dc: dc,
- nspace: nspace,
- },
- });
- })
- );
+ assert.equal(actual.uid, `["${nspace}","${dc}","${actual.ID}"]`);
+ assert.equal(actual.Datacenter, dc);
}
);
});
diff --git a/ui/packages/consul-ui/tests/pages.js b/ui/packages/consul-ui/tests/pages.js
index fda98b6ef..e69f3dfb7 100644
--- a/ui/packages/consul-ui/tests/pages.js
+++ b/ui/packages/consul-ui/tests/pages.js
@@ -40,6 +40,7 @@ import popoverSelectFactory from 'consul-ui/components/popover-select/pageobject
import morePopoverMenuFactory from 'consul-ui/components/more-popover-menu/pageobject';
import tokenListFactory from 'consul-ui/components/token-list/pageobject';
+import consulHealthCheckListFactory from 'consul-ui/components/consul/health-check/list/pageobject';
import consulUpstreamInstanceListFactory from 'consul-ui/components/consul/upstream-instance/list/pageobject';
import consulTokenListFactory from 'consul-ui/components/consul/token/list/pageobject';
import consulRoleListFactory from 'consul-ui/components/consul/role/list/pageobject';
@@ -95,6 +96,7 @@ const morePopoverMenu = morePopoverMenuFactory(clickable);
const popoverSelect = popoverSelectFactory(clickable, collection);
const emptyState = emptyStateFactory(isPresent);
+const consulHealthCheckList = consulHealthCheckListFactory(collection, text);
const consulUpstreamInstanceList = consulUpstreamInstanceListFactory(collection, text);
const consulIntentionList = consulIntentionListFactory(
collection,
@@ -162,10 +164,30 @@ export default {
service(visitable, attribute, collection, text, consulIntentionList, catalogToolbar, tabgroup)
),
instance: create(
- instance(visitable, alias, attribute, collection, text, tabgroup, consulUpstreamInstanceList)
+ instance(
+ visitable,
+ alias,
+ attribute,
+ collection,
+ text,
+ tabgroup,
+ consulUpstreamInstanceList,
+ consulHealthCheckList
+ )
),
nodes: create(nodes(visitable, text, clickable, attribute, collection, popoverSelect)),
- node: create(node(visitable, deletable, clickable, attribute, collection, tabgroup, text)),
+ node: create(
+ node(
+ visitable,
+ deletable,
+ clickable,
+ attribute,
+ collection,
+ tabgroup,
+ text,
+ consulHealthCheckList
+ )
+ ),
kvs: create(kvs(visitable, creatable, consulKvList)),
kv: create(kv(visitable, attribute, submitable, deletable, cancelable, clickable)),
acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)),
diff --git a/ui/packages/consul-ui/tests/pages/dc/nodes/show.js b/ui/packages/consul-ui/tests/pages/dc/nodes/show.js
index d3780143a..7be58fabf 100644
--- a/ui/packages/consul-ui/tests/pages/dc/nodes/show.js
+++ b/ui/packages/consul-ui/tests/pages/dc/nodes/show.js
@@ -1,4 +1,13 @@
-export default function(visitable, deletable, clickable, attribute, collection, tabs, text) {
+export default function(
+ visitable,
+ deletable,
+ clickable,
+ attribute,
+ collection,
+ tabs,
+ text,
+ healthChecks
+) {
return {
visit: visitable('/:dc/nodes/:node'),
tabs: tabs('tab', [
@@ -8,9 +17,7 @@ export default function(visitable, deletable, clickable, attribute, collection,
'lock-sessions',
'metadata',
]),
- healthchecks: collection('[data-test-node-healthcheck]', {
- name: attribute('data-test-node-healthcheck'),
- }),
+ healthChecks: healthChecks(),
services: collection('.consul-service-instance-list > ul > li:not(:first-child)', {
name: text('[data-test-service-name]'),
port: attribute('data-test-service-port', '[data-test-service-port]'),
diff --git a/ui/packages/consul-ui/tests/pages/dc/services/instance.js b/ui/packages/consul-ui/tests/pages/dc/services/instance.js
index 33ec95697..b942c0b10 100644
--- a/ui/packages/consul-ui/tests/pages/dc/services/instance.js
+++ b/ui/packages/consul-ui/tests/pages/dc/services/instance.js
@@ -1,17 +1,26 @@
-export default function(visitable, alias, attribute, collection, text, tabs, upstreams) {
+export default function(
+ visitable,
+ alias,
+ attribute,
+ collection,
+ text,
+ tabs,
+ upstreams,
+ healthChecks
+) {
return {
visit: visitable('/:dc/services/:service/instances/:node/:id'),
externalSource: attribute('data-test-external-source', '[data-test-external-source]', {
scope: '.title',
}),
tabs: tabs('tab', ['health-checks', 'upstreams', 'exposed-paths', 'addresses', 'tags-&-meta']),
- checks: collection('[data-test-checks] li'),
+ checks: alias('healthChecks.item'),
+ healthChecks: healthChecks(),
upstreams: alias('upstreamInstances.item'),
upstreamInstances: upstreams(),
exposedPaths: collection('[data-test-proxy-exposed-paths] > tbody tr', {
combinedAddress: text('[data-test-combined-address]'),
}),
- proxyChecks: collection('[data-test-proxy-checks] li'),
addresses: collection('#addresses [data-test-tabular-row]', {
address: text('[data-test-address]'),
}),