mirror of https://github.com/status-im/consul.git
ui: Split ember-data service model into service/service-instance (#8557)
This commit is contained in:
parent
ad9f118d14
commit
1846e6316c
|
@ -0,0 +1,23 @@
|
|||
import Adapter from './application';
|
||||
// TODO: Update to use this.formatDatacenter()
|
||||
export default Adapter.extend({
|
||||
requestForQuery: function(request, { dc, ns, index, id, uri }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return request`
|
||||
GET /v1/health/service/${id}?${{ dc }}
|
||||
X-Request-ID: ${uri}
|
||||
|
||||
${{
|
||||
...this.formatNspace(ns),
|
||||
index,
|
||||
}}
|
||||
`;
|
||||
},
|
||||
requestForQueryRecord: function(request, { dc, ns, index, id, uri }) {
|
||||
// query and queryRecord both use the same endpoint
|
||||
// they are just serialized differently
|
||||
return this.requestForQuery(...arguments);
|
||||
},
|
||||
});
|
|
@ -20,7 +20,7 @@
|
|||
<ConsulInstanceChecks @type="service" @items={{filter-by 'ServiceID' '' item.Checks}} />
|
||||
<ConsulInstanceChecks @type="node" @items={{reject-by 'ServiceID' '' item.Checks}} />
|
||||
{{/if}}
|
||||
{{#if (get proxies item.Service.ID)}}
|
||||
{{#if item.ProxyInstance}}
|
||||
<dl class="proxy">
|
||||
<dt>
|
||||
<Tooltip>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import Controller from '@ember/controller';
|
||||
import { get } from '@ember/object';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import { inject as service } from '@ember/service';
|
||||
export default Controller.extend({
|
||||
dom: service('dom'),
|
||||
notify: service('flashMessages'),
|
||||
item: alias('items.firstObject'),
|
||||
actions: {
|
||||
error: function(e) {
|
||||
if (e.target.readyState === 1) {
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import Controller from '@ember/controller';
|
||||
import { computed } from '@ember/object';
|
||||
import { alias } from '@ember/object/computed';
|
||||
|
||||
export default Controller.extend({
|
||||
items: alias('item.Nodes'),
|
||||
queryParams: {
|
||||
sortBy: 'sort',
|
||||
search: {
|
||||
|
@ -11,12 +8,4 @@ export default Controller.extend({
|
|||
replace: true,
|
||||
},
|
||||
},
|
||||
keyedProxies: computed('proxies.[]', function() {
|
||||
const proxies = {};
|
||||
this.proxies.forEach(item => {
|
||||
proxies[item.ServiceProxy.DestinationServiceID] = true;
|
||||
});
|
||||
|
||||
return proxies;
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import Model from 'ember-data/model';
|
||||
import attr from 'ember-data/attr';
|
||||
import { belongsTo } from 'ember-data/relationships';
|
||||
import { filter, alias } from '@ember/object/computed';
|
||||
|
||||
export const PRIMARY_KEY = 'uid';
|
||||
export const SLUG_KEY = 'Node.Node,Service.ID';
|
||||
|
||||
export default Model.extend({
|
||||
[PRIMARY_KEY]: attr('string'),
|
||||
[SLUG_KEY]: attr('string'),
|
||||
Datacenter: attr('string'),
|
||||
// ProxyInstance is the ember-data model relationship
|
||||
ProxyInstance: belongsTo('Proxy'),
|
||||
// Proxy is the actual JSON api response
|
||||
Proxy: attr(),
|
||||
Node: attr(),
|
||||
Service: attr(),
|
||||
Checks: attr(),
|
||||
SyncTime: attr('number'),
|
||||
meta: attr(),
|
||||
Tags: alias('Service.Tags'),
|
||||
Meta: alias('Service.Meta'),
|
||||
Namespace: alias('Service.Namespace'),
|
||||
ServiceChecks: filter('Checks', function(item, i, arr) {
|
||||
return item.ServiceID !== '';
|
||||
}),
|
||||
NodeChecks: filter('Checks', function(item, i, arr) {
|
||||
return item.ServiceID === '';
|
||||
}),
|
||||
});
|
|
@ -14,8 +14,8 @@ export default Model.extend({
|
|||
},
|
||||
}),
|
||||
InstanceCount: attr('number'),
|
||||
ProxyFor: attr(),
|
||||
Proxy: attr(),
|
||||
ProxyFor: attr(),
|
||||
Kind: attr('string'),
|
||||
ExternalSources: attr(),
|
||||
GatewayConfig: attr(),
|
||||
|
|
|
@ -10,7 +10,7 @@ export default Route.extend({
|
|||
return this.modelFor(parent);
|
||||
},
|
||||
afterModel: function(model, transition) {
|
||||
if (get(model, 'item.Kind') !== 'mesh-gateway') {
|
||||
if (get(model, 'item.Service.Kind') !== 'mesh-gateway') {
|
||||
const parent = this.routeName
|
||||
.split('.')
|
||||
.slice(0, -1)
|
||||
|
|
|
@ -10,7 +10,7 @@ export default Route.extend({
|
|||
return this.modelFor(parent);
|
||||
},
|
||||
afterModel: function(model, transition) {
|
||||
if (get(model, 'item.Kind') !== 'connect-proxy') {
|
||||
if (get(model, 'item.Service.Kind') !== 'connect-proxy') {
|
||||
const parent = this.routeName
|
||||
.split('.')
|
||||
.slice(0, -1)
|
||||
|
|
|
@ -13,13 +13,15 @@ export default Route.extend({
|
|||
slug: params.name,
|
||||
dc: dc,
|
||||
nspace: nspace,
|
||||
item: this.data.source(uri => uri`/${nspace}/${dc}/service/${params.name}`),
|
||||
items: this.data.source(
|
||||
uri => uri`/${nspace}/${dc}/service-instances/for-service/${params.name}`
|
||||
),
|
||||
urls: this.settings.findBySlug('urls'),
|
||||
proxies: [],
|
||||
})
|
||||
.then(model => {
|
||||
return ['connect-proxy', 'mesh-gateway', 'ingress-gateway', 'terminating-gateway'].includes(
|
||||
get(model, 'item.Service.Kind')
|
||||
get(model, 'items.firstObject.Service.Kind')
|
||||
)
|
||||
? model
|
||||
: hash({
|
||||
|
@ -31,7 +33,9 @@ export default Route.extend({
|
|||
});
|
||||
})
|
||||
.then(model => {
|
||||
return ['ingress-gateway', 'terminating-gateway'].includes(get(model, 'item.Service.Kind'))
|
||||
return ['ingress-gateway', 'terminating-gateway'].includes(
|
||||
get(model, 'items.firstObject.Service.Kind')
|
||||
)
|
||||
? hash({
|
||||
...model,
|
||||
gatewayServices: this.data.source(
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import Serializer from './application';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/service-instance';
|
||||
|
||||
export default Serializer.extend({
|
||||
primaryKey: PRIMARY_KEY,
|
||||
slugKey: SLUG_KEY,
|
||||
respondForQuery: function(respond, query) {
|
||||
return this._super(function(cb) {
|
||||
return respond(function(headers, body) {
|
||||
if (body.length === 0) {
|
||||
const e = new Error();
|
||||
e.errors = [
|
||||
{
|
||||
status: '404',
|
||||
title: 'Not found',
|
||||
},
|
||||
];
|
||||
throw e;
|
||||
}
|
||||
return cb(headers, body);
|
||||
});
|
||||
}, query);
|
||||
},
|
||||
respondForQueryRecord: function(respond, query) {
|
||||
return this._super(function(cb) {
|
||||
return respond(function(headers, body) {
|
||||
body = body.find(function(item) {
|
||||
return item.Node.Node === query.node && item.Service.ID === query.serviceId;
|
||||
});
|
||||
if (typeof body === 'undefined') {
|
||||
const e = new Error();
|
||||
e.errors = [
|
||||
{
|
||||
status: '404',
|
||||
title: 'Not found',
|
||||
},
|
||||
];
|
||||
throw e;
|
||||
}
|
||||
body.Namespace = body.Service.Namespace;
|
||||
return cb(headers, body);
|
||||
});
|
||||
}, query);
|
||||
},
|
||||
});
|
|
@ -8,7 +8,8 @@ export default Service.extend({
|
|||
gateways: service('repository/service'),
|
||||
services: service('repository/service'),
|
||||
service: service('repository/service'),
|
||||
['service-instance']: service('repository/service'),
|
||||
['service-instance']: service('repository/service-instance'),
|
||||
['service-instances']: service('repository/service-instance'),
|
||||
proxies: service('repository/proxy'),
|
||||
['proxy-instance']: service('repository/proxy'),
|
||||
['discovery-chain']: service('repository/discovery-chain'),
|
||||
|
@ -67,6 +68,14 @@ export default Service.extend({
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case 'service-instances':
|
||||
[method, ...slug] = rest;
|
||||
switch (method) {
|
||||
case 'for-service':
|
||||
find = configuration => repo.findByService(slug, dc, nspace, configuration);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'coordinates':
|
||||
[method, ...slug] = rest;
|
||||
switch (method) {
|
||||
|
@ -102,12 +111,15 @@ export default Service.extend({
|
|||
case 'token':
|
||||
find = configuration => repo.self(rest[1], dc);
|
||||
break;
|
||||
case 'service':
|
||||
case 'discovery-chain':
|
||||
case 'node':
|
||||
find = configuration => repo.findBySlug(rest[0], dc, nspace, configuration);
|
||||
break;
|
||||
case 'service-instance':
|
||||
// id, node, service
|
||||
find = configuration =>
|
||||
repo.findBySlug(rest[0], rest[1], rest[2], dc, nspace, configuration);
|
||||
break;
|
||||
case 'proxy-instance':
|
||||
// id, node, service
|
||||
find = configuration =>
|
||||
|
|
|
@ -19,7 +19,20 @@ export default RepositoryService.extend({
|
|||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
}
|
||||
return this.store.query(this.getModelName(), query);
|
||||
return this.store.query(this.getModelName(), query).then(items => {
|
||||
items.forEach(item => {
|
||||
// swap out the id for the services id
|
||||
// so we can then assign the proxy to it if it exists
|
||||
const id = JSON.parse(item.uid);
|
||||
id.pop();
|
||||
id.push(item.ServiceProxy.DestinationServiceID);
|
||||
const service = this.store.peekRecord('service-instance', JSON.stringify(id));
|
||||
if (service) {
|
||||
set(service, 'ProxyInstance', item);
|
||||
}
|
||||
});
|
||||
return items;
|
||||
});
|
||||
},
|
||||
findInstanceBySlug: function(id, node, slug, dc, nspace, configuration) {
|
||||
return this.findAllBySlug(slug, dc, nspace, configuration).then(function(items) {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
const modelName = 'service-instance';
|
||||
export default RepositoryService.extend({
|
||||
getModelName: function() {
|
||||
return modelName;
|
||||
},
|
||||
findByService: function(slug, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
nspace: nspace,
|
||||
id: slug,
|
||||
};
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
}
|
||||
return this.store.query(this.getModelName(), query);
|
||||
},
|
||||
findBySlug: function(serviceId, node, service, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
serviceId: serviceId,
|
||||
node: node,
|
||||
id: service,
|
||||
};
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
}
|
||||
return this.store.queryRecord(this.getModelName(), query);
|
||||
},
|
||||
});
|
|
@ -1,74 +1,9 @@
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import { get, set } from '@ember/object';
|
||||
const modelName = 'service';
|
||||
export default RepositoryService.extend({
|
||||
getModelName: function() {
|
||||
return modelName;
|
||||
},
|
||||
findBySlug: function(slug, dc) {
|
||||
return this._super(...arguments).then(function(item) {
|
||||
// TODO: Move this to the Serializer
|
||||
const nodes = get(item, 'Nodes');
|
||||
if (nodes.length === 0) {
|
||||
// TODO: Add an store.error("404", "message") or similar
|
||||
// or move all this to serializer
|
||||
const e = new Error();
|
||||
e.errors = [
|
||||
{
|
||||
status: '404',
|
||||
title: 'Not found',
|
||||
},
|
||||
];
|
||||
throw e;
|
||||
}
|
||||
const service = get(nodes, 'firstObject');
|
||||
// TODO: Use [...new Set()] instead of uniq
|
||||
const tags = nodes
|
||||
.reduce(function(prev, item) {
|
||||
return prev.concat(get(item, 'Service.Tags') || []);
|
||||
}, [])
|
||||
.uniq();
|
||||
set(service, 'Tags', tags);
|
||||
set(service, 'Nodes', nodes);
|
||||
set(service, 'meta', get(item, 'meta'));
|
||||
set(service, 'Namespace', get(item, 'Namespace'));
|
||||
return service;
|
||||
});
|
||||
},
|
||||
findInstanceBySlug: function(id, node, slug, dc, nspace, configuration) {
|
||||
return this.findBySlug(slug, dc, nspace, configuration).then(function(item) {
|
||||
// TODO: Move this to the Serializer
|
||||
// Loop through all the service instances and pick out the one
|
||||
// that has the same service id AND node name
|
||||
// node names are unique per datacenter
|
||||
const i = item.Nodes.findIndex(function(item) {
|
||||
return item.Service.ID === id && item.Node.Node === node;
|
||||
});
|
||||
if (i !== -1) {
|
||||
const service = item.Nodes[i].Service;
|
||||
service.Node = item.Nodes[i].Node;
|
||||
service.ServiceChecks = item.Nodes[i].Checks.filter(function(item) {
|
||||
return item.ServiceID != '';
|
||||
});
|
||||
service.NodeChecks = item.Nodes[i].Checks.filter(function(item) {
|
||||
return item.ServiceID == '';
|
||||
});
|
||||
set(service, 'meta', get(item, 'meta'));
|
||||
set(service, 'Namespace', get(item, 'Namespace'));
|
||||
return service;
|
||||
}
|
||||
// TODO: Add an store.error("404", "message") or similar
|
||||
// or move all this to serializer
|
||||
const e = new Error();
|
||||
e.errors = [
|
||||
{
|
||||
status: '404',
|
||||
title: 'Unable to find instance',
|
||||
},
|
||||
];
|
||||
throw e;
|
||||
});
|
||||
},
|
||||
findGatewayBySlug: function(slug, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{{title item.ID}}
|
||||
{{title item.Service.ID}}
|
||||
<EventSource @src={{item}} @onerror={{action "error"}} />
|
||||
<EventSource @src={{proxy}} />
|
||||
<EventSource @src={{proxyMeta}} />
|
||||
|
@ -9,12 +9,12 @@
|
|||
<BlockSlot @name="breadcrumbs">
|
||||
<ol>
|
||||
<li><a data-test-back href={{href-to 'dc.services'}}>All Services</a></li>
|
||||
<li><a data-test-back href={{href-to 'dc.services.show'}}>Service ({{item.Service}})</a></li>
|
||||
<li><a data-test-back href={{href-to 'dc.services.show'}}>Service ({{item.Service.Service}})</a></li>
|
||||
</ol>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
{{ item.ID }}
|
||||
{{ item.Service.ID }}
|
||||
</h1>
|
||||
<ConsulExternalSource @item={{item}} />
|
||||
<ConsulKind @item={{item}} @withInfo={{true}} />
|
||||
|
@ -22,7 +22,7 @@
|
|||
<BlockSlot @name="nav">
|
||||
<dl>
|
||||
<dt>Service Name</dt>
|
||||
<dd><a href="{{href-to 'dc.services.show' item.Service}}">{{item.Service}}</a></dd>
|
||||
<dd><a href="{{href-to 'dc.services.show' item.Service.Service}}">{{item.Service.Service}}</a></dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Node Name</dt>
|
||||
|
@ -30,7 +30,7 @@
|
|||
</dl>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
{{#let (or item.Address item.Node.Address) as |address|}}
|
||||
{{#let (or item.Service.Address item.Node.Address) as |address|}}
|
||||
<CopyButton @value={{address}} @name="Address">{{address}}</CopyButton>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
|
@ -40,7 +40,7 @@
|
|||
(array
|
||||
(hash label="Health Checks" href=(href-to "dc.services.instance.healthchecks") selected=(is-href "dc.services.instance.healthchecks"))
|
||||
(if
|
||||
(eq item.Kind 'mesh-gateway')
|
||||
(eq item.Service.Kind 'mesh-gateway')
|
||||
(hash label="Addresses" href=(href-to "dc.services.instance.addresses") selected=(is-href "dc.services.instance.addresses")) ""
|
||||
)
|
||||
(if proxy
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div id="addresses" class="tab-section">
|
||||
<div role="tabpanel">
|
||||
{{#if item.TaggedAddresses }}
|
||||
{{#if item.Service.TaggedAddresses }}
|
||||
<TabularCollection
|
||||
data-test-addresses
|
||||
@items={{object-entries item.TaggedAddresses}} as |taggedAddress index|
|
||||
@items={{object-entries item.Service.TaggedAddresses}} as |taggedAddress index|
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<th>Tag</th>
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<div class="tab-section">
|
||||
<div role="tabpanel">
|
||||
{{#if (gt proxy.Proxy.Upstreams.length 0)}}
|
||||
{{#if (gt proxy.Service.Proxy.Upstreams.length 0)}}
|
||||
<section class="proxy-upstreams">
|
||||
<h3>Upstreams</h3>
|
||||
<ConsulUpstreamInstanceList @items={{proxy.Proxy.Upstreams}} @dc={{dc}} @nspace={{nspace}} />
|
||||
<ConsulUpstreamInstanceList @items={{proxy.Service.Proxy.Upstreams}} @dc={{dc}} @nspace={{nspace}} />
|
||||
</section>
|
||||
{{/if}}
|
||||
{{#if (gt proxy.Proxy.Expose.Paths.length 0)}}
|
||||
{{#if (gt proxy.Service.Proxy.Expose.Paths.length 0)}}
|
||||
<section class="proxy-exposed-paths">
|
||||
<h3>Exposed paths</h3>
|
||||
<p>
|
||||
The following list shows individual HTTP paths exposed through Envoy for external services like Prometheus. Read more about this in our documentation.
|
||||
</p>
|
||||
<ConsulExposedPathList @items={{proxy.Proxy.Expose.Paths}} @address={{item.Address}} />
|
||||
<ConsulExposedPathList @items={{proxy.Service.Proxy.Expose.Paths}} @address={{item.Address}} />
|
||||
</section>
|
||||
{{/if}}
|
||||
{{#if (or (gt proxy.ServiceChecks.length 0) (gt proxy.NodeChecks.length 0))}}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{{title item.Service.Service}}
|
||||
<EventSource @src={{item}} @onerror={{action "error"}} />
|
||||
<EventSource @src={{items}} @onerror={{action "error"}} />
|
||||
<EventSource @src={{chain}} />
|
||||
<EventSource @src={{intentions}} />
|
||||
<EventSource @src={{proxies}} />
|
||||
<EventSource @src={{gatewayServices}} />
|
||||
{{title item.Service.Service}}
|
||||
<AppView @class="service show">
|
||||
<BlockSlot @name="notification" as |status type|>
|
||||
{{partial 'dc/services/notifications'}}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{{/if}}
|
||||
<ChangeableSet @dispatcher={{searchable 'serviceInstance' items}} @terms={{search}}>
|
||||
<BlockSlot @name="set" as |filtered|>
|
||||
<ConsulServiceInstanceList @routeName="dc.services.instance" @items={{filtered}} @proxies={{keyedProxies}}/>
|
||||
<ConsulServiceInstanceList @routeName="dc.services.instance" @items={{filtered}}/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="empty">
|
||||
<EmptyState>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<div id="tags" class="tab-section">
|
||||
<div role="tabpanel">
|
||||
{{#if (gt item.Tags.length 0) }}
|
||||
<TagList @item={{item}} />
|
||||
{{else}}
|
||||
{{#let (flatten (map-by "Tags" items)) as |tags|}}
|
||||
{{#if (gt tags.length 0) }}
|
||||
<TagList @item={{hash Tags=tags}} />
|
||||
{{else}}
|
||||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
|
@ -10,6 +11,7 @@
|
|||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { get } from '@ember/object';
|
||||
export default function(foreignKey, nspaceKey, hash = JSON.stringify) {
|
||||
return function(primaryKey, slugKey, foreignKeyValue) {
|
||||
if (foreignKeyValue == null || foreignKeyValue.length < 1) {
|
||||
|
@ -6,12 +7,12 @@ export default function(foreignKey, nspaceKey, hash = JSON.stringify) {
|
|||
return function(item) {
|
||||
const slugKeys = slugKey.split(',');
|
||||
const slugValues = slugKeys.map(function(slugKey) {
|
||||
if (item[slugKey] == null || item[slugKey].length < 1) {
|
||||
if (get(item, slugKey) == null || get(item, slugKey).length < 1) {
|
||||
throw new Error('Unable to create fingerprint, missing slug');
|
||||
}
|
||||
return item[slugKey];
|
||||
return get(item, slugKey);
|
||||
});
|
||||
const nspaceValue = item[nspaceKey] || 'default';
|
||||
const nspaceValue = get(item, nspaceKey) || 'default';
|
||||
return {
|
||||
...item,
|
||||
...{
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { env } from '../../../env';
|
||||
const shouldHaveNspace = function(nspace) {
|
||||
return typeof nspace !== 'undefined' && env('CONSUL_NSPACES_ENABLED');
|
||||
};
|
||||
module('Integration | Adapter | service-instance', function(hooks) {
|
||||
setupTest(hooks);
|
||||
const dc = 'dc-1';
|
||||
const id = 'service-name';
|
||||
const undefinedNspace = 'default';
|
||||
[undefinedNspace, 'team-1', undefined].forEach(nspace => {
|
||||
test(`requestForQueryRecord returns the correct url/method when nspace is ${nspace}`, function(assert) {
|
||||
const adapter = this.owner.lookup('adapter:service-instance');
|
||||
const client = this.owner.lookup('service:client/http');
|
||||
const expected = `GET /v1/health/service/${id}?dc=${dc}${
|
||||
shouldHaveNspace(nspace) ? `&ns=${nspace}` : ``
|
||||
}`;
|
||||
let actual = adapter.requestForQueryRecord(client.requestParams.bind(client), {
|
||||
dc: dc,
|
||||
id: id,
|
||||
ns: nspace,
|
||||
});
|
||||
assert.equal(`${actual.method} ${actual.url}`, expected);
|
||||
});
|
||||
});
|
||||
test("requestForQueryRecord throws if you don't specify an id", function(assert) {
|
||||
const adapter = this.owner.lookup('adapter:service-instance');
|
||||
const client = this.owner.lookup('service:client/http');
|
||||
assert.throws(function() {
|
||||
adapter.requestForQueryRecord(client.url, {
|
||||
dc: dc,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,54 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { get } from 'consul-ui/tests/helpers/api';
|
||||
import {
|
||||
HEADERS_SYMBOL as META,
|
||||
HEADERS_DATACENTER as DC,
|
||||
HEADERS_NAMESPACE as NSPACE,
|
||||
} from 'consul-ui/utils/http/consul';
|
||||
module('Integration | Serializer | service-instance', function(hooks) {
|
||||
setupTest(hooks);
|
||||
const dc = 'dc-1';
|
||||
const undefinedNspace = 'default';
|
||||
[undefinedNspace, 'team-1', undefined].forEach(nspace => {
|
||||
test(`respondForQueryRecord returns the correct data for item endpoint when nspace is ${nspace}`, function(assert) {
|
||||
const serializer = this.owner.lookup('serializer:service-instance');
|
||||
const id = 'service-name';
|
||||
const node = 'node-0';
|
||||
const request = {
|
||||
url: `/v1/health/service/${id}?dc=${dc}${
|
||||
typeof nspace !== 'undefined' ? `&ns=${nspace}` : ``
|
||||
}`,
|
||||
};
|
||||
return get(request.url).then(function(payload) {
|
||||
payload[0].Node.Node = node;
|
||||
payload[0].Service.ID = id;
|
||||
const expected = {
|
||||
...payload[0],
|
||||
Datacenter: dc,
|
||||
[META]: {
|
||||
[DC.toLowerCase()]: dc,
|
||||
[NSPACE.toLowerCase()]: payload[0].Service.Namespace || undefinedNspace,
|
||||
},
|
||||
Namespace: payload[0].Service.Namespace || undefinedNspace,
|
||||
uid: `["${payload[0].Service.Namespace || undefinedNspace}","${dc}","${node}","${id}"]`,
|
||||
};
|
||||
const actual = serializer.respondForQueryRecord(
|
||||
function(cb) {
|
||||
const headers = {};
|
||||
const body = payload;
|
||||
return cb(headers, body);
|
||||
},
|
||||
{
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
id: id,
|
||||
node: node,
|
||||
serviceId: id,
|
||||
}
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,11 +1,6 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { get } from 'consul-ui/tests/helpers/api';
|
||||
import {
|
||||
HEADERS_SYMBOL as META,
|
||||
HEADERS_DATACENTER as DC,
|
||||
HEADERS_NAMESPACE as NSPACE,
|
||||
} from 'consul-ui/utils/http/consul';
|
||||
module('Integration | Serializer | service', function(hooks) {
|
||||
setupTest(hooks);
|
||||
const dc = 'dc-1';
|
||||
|
@ -73,40 +68,5 @@ module('Integration | Serializer | service', function(hooks) {
|
|||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
test(`respondForQueryRecord returns the correct data for item endpoint when nspace is ${nspace}`, function(assert) {
|
||||
const serializer = this.owner.lookup('serializer:service');
|
||||
const id = 'service-name';
|
||||
const request = {
|
||||
url: `/v1/health/service/${id}?dc=${dc}${
|
||||
typeof nspace !== 'undefined' ? `&ns=${nspace}` : ``
|
||||
}`,
|
||||
};
|
||||
return get(request.url).then(function(payload) {
|
||||
const expected = {
|
||||
Datacenter: dc,
|
||||
[META]: {
|
||||
[DC.toLowerCase()]: dc,
|
||||
[NSPACE.toLowerCase()]: payload[0].Service.Namespace || undefinedNspace,
|
||||
},
|
||||
Namespace: payload[0].Service.Namespace || undefinedNspace,
|
||||
uid: `["${payload[0].Service.Namespace || undefinedNspace}","${dc}","${id}"]`,
|
||||
Name: id,
|
||||
Nodes: payload,
|
||||
};
|
||||
const actual = serializer.respondForQueryRecord(
|
||||
function(cb) {
|
||||
const headers = {};
|
||||
const body = payload;
|
||||
return cb(headers, body);
|
||||
},
|
||||
{
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
id: id,
|
||||
}
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,89 +7,9 @@ moduleFor(`service:repository/${NAME}`, `Integration | Service | ${NAME}`, {
|
|||
integration: true,
|
||||
});
|
||||
const dc = 'dc-1';
|
||||
const id = 'token-name';
|
||||
const now = new Date().getTime();
|
||||
const undefinedNspace = 'default';
|
||||
[undefinedNspace, 'team-1', undefined].forEach(nspace => {
|
||||
test(`findInstanceBySlug calls findBySlug with the correct arguments when nspace is ${nspace}`, function(assert) {
|
||||
assert.expect(4);
|
||||
const id = 'id';
|
||||
const slug = 'slug';
|
||||
const node = 'node-name';
|
||||
|
||||
const datacenter = 'dc-1';
|
||||
const conf = {
|
||||
cursor: 1,
|
||||
};
|
||||
const service = this.subject();
|
||||
service.findBySlug = function(slug, dc, nspace, configuration) {
|
||||
assert.equal(
|
||||
arguments.length,
|
||||
4,
|
||||
'Expected to be called with the correct number of arguments'
|
||||
);
|
||||
assert.equal(dc, datacenter);
|
||||
assert.deepEqual(configuration, conf);
|
||||
return Promise.resolve({ Nodes: [] });
|
||||
};
|
||||
// This will throw an error as we don't resolve any services that match what was requested
|
||||
// so a 404 is the correct error response
|
||||
return service.findInstanceBySlug(id, slug, node, datacenter, nspace, conf).catch(function(e) {
|
||||
assert.equal(e.errors[0].status, '404');
|
||||
});
|
||||
});
|
||||
|
||||
test(`findBySlug returns the correct data for item endpoint when the nspace is ${nspace}`, function(assert) {
|
||||
return repo(
|
||||
'Service',
|
||||
'findBySlug',
|
||||
this.subject(),
|
||||
function(stub) {
|
||||
return stub(
|
||||
`/v1/health/service/${id}?dc=${dc}${
|
||||
typeof nspace !== 'undefined' ? `&ns=${nspace}` : ``
|
||||
}`,
|
||||
{
|
||||
CONSUL_NODE_COUNT: 1,
|
||||
}
|
||||
);
|
||||
},
|
||||
function(service) {
|
||||
return service.findBySlug(id, dc, nspace || undefinedNspace);
|
||||
},
|
||||
function(actual, expected) {
|
||||
assert.deepEqual(
|
||||
actual,
|
||||
expected(function(payload) {
|
||||
// TODO: So this tree is all 'wrong', it's not having any major impact
|
||||
// this this tree needs revisting to something that makes more sense
|
||||
payload = Object.assign(
|
||||
{},
|
||||
{ Nodes: payload },
|
||||
{
|
||||
Datacenter: dc,
|
||||
Namespace: payload[0].Service.Namespace || undefinedNspace,
|
||||
uid: `["${payload[0].Service.Namespace || undefinedNspace}","${dc}","${id}"]`,
|
||||
}
|
||||
);
|
||||
const nodes = payload.Nodes;
|
||||
const service = payload.Nodes[0];
|
||||
service.Nodes = nodes;
|
||||
service.Tags = [...new Set(payload.Nodes[0].Service.Tags)];
|
||||
service.Namespace = payload.Namespace;
|
||||
service.meta = {
|
||||
cacheControl: undefined,
|
||||
cursor: undefined,
|
||||
dc: dc,
|
||||
nspace: payload.Namespace,
|
||||
};
|
||||
|
||||
return service;
|
||||
})
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
test(`findGatewayBySlug returns the correct data for list endpoint when nspace is ${nspace}`, function(assert) {
|
||||
get(this.subject(), 'store').serializerFor(NAME).timestamp = function() {
|
||||
return now;
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Adapter | service-instance', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let adapter = this.owner.lookup('adapter:service-instance');
|
||||
assert.ok(adapter);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Model | service-instance', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let store = this.owner.lookup('service:store');
|
||||
let model = store.createRecord('service-instance', {});
|
||||
assert.ok(model);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Serializer | service-instance', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let store = this.owner.lookup('service:store');
|
||||
let serializer = store.serializerFor('service-instance');
|
||||
|
||||
assert.ok(serializer);
|
||||
});
|
||||
|
||||
test('it serializes records', function(assert) {
|
||||
let store = this.owner.lookup('service:store');
|
||||
let record = store.createRecord('service-instance', {});
|
||||
|
||||
let serializedRecord = record.serialize();
|
||||
|
||||
assert.ok(serializedRecord);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Repository | service-instance', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
const repo = this.owner.lookup('service:repository/service-instance');
|
||||
assert.ok(repo);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue