ui: DataSource Decorator (#9746)
We use a `<DataSource @src={{url}} />` component throughout our UI for when we want to load data from within our components. The URL specified as the `@src` is used to map/lookup what is used in to retrieve data, for example we mostly use our repository methods wrapped with our Promise backed `EventSource` implementation, but DataSource URLs can also be mapped to EventTarget backed `EventSource`s and native `EventSource`s or `WebSockets` if we ever need to use those (for example these are options for potential streaming support with the Consul backend). The URL to function/method mapping previous to this PR used a very naive humongous `switch` statement which was a temporary 'this is fine for the moment' solution, although we'd always wanted to replace with something more manageable. Here we add `wayfarer` as a dependency - a very small (1kb), very fast, radix trie based router, and use that to perform the URL to function/method mapping. This essentially turns every `DataSource` into a very small SPA - change its URL and the view of data changes. When the data itself changes, either the yielded view of data changes or the `onchange` event is fired with the changed data, making the externally sourced view of data completely reactive. ```javascript // use the new decorator a service somewhere to annotate/decorate // a method with the URL that can be used to access this method @dataSource('/:ns/:dc/services') async findAllByDatacenter(params) { // get the data } // can use with JS in a route somewhere async model() { return this.data.source(uri => uri`/${nspace}/${dc}/services`) } ``` ```hbs {{!-- or just straight in a template using the component --}} <DataSource @src="/default/dc1/services" @onchange="" /> ``` This also uses a new `container` Service to automatically execute/import certain services yet not execute them. This new service also provides a lookup that supports both standard ember DI lookup plus Class based lookup or these specific services. Lastly we also provide another debug function called DataSourceRoutes() which can be called from console which gives you a list of URLs and their mappings.
This commit is contained in:
parent
ea7f543498
commit
fbbdc4d352
|
@ -4,20 +4,20 @@ import { inject as service } from '@ember/service';
|
|||
export default class PermissionAdapter extends Adapter {
|
||||
@service('env') env;
|
||||
|
||||
requestForAuthorize(request, { dc, ns, permissions = [], index }) {
|
||||
requestForAuthorize(request, { dc, ns, resources = [], index }) {
|
||||
// the authorize endpoint is slightly different to all others in that it
|
||||
// ignores an ns parameter, but accepts a Namespace property on each
|
||||
// resource. Here we hide this different from the rest of the app as
|
||||
// currently we never need to ask for permissions/resources for mutiple
|
||||
// currently we never need to ask for permissions/resources for multiple
|
||||
// different namespaces in one call so here we use the ns param and add
|
||||
// this to the resources instead of passing through on the queryParameter
|
||||
if (this.env.var('CONSUL_NSPACES_ENABLED')) {
|
||||
permissions = permissions.map(item => ({ ...item, Namespace: ns }));
|
||||
resources = resources.map(item => ({ ...item, Namespace: ns }));
|
||||
}
|
||||
return request`
|
||||
POST /v1/internal/acl/authorize?${{ dc, index }}
|
||||
|
||||
${permissions}
|
||||
${resources}
|
||||
`;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import { runInDebug } from '@ember/debug';
|
||||
import wayfarer from 'wayfarer';
|
||||
|
||||
const router = wayfarer();
|
||||
const routes = {};
|
||||
export default path => (target, propertyKey, desc) => {
|
||||
runInDebug(() => {
|
||||
routes[path] = { cls: target, method: propertyKey };
|
||||
});
|
||||
router.on(path, function(params, owner) {
|
||||
const container = owner.lookup('service:container');
|
||||
const instance = container.get(target);
|
||||
return configuration => desc.value.apply(instance, [params, configuration]);
|
||||
});
|
||||
return desc;
|
||||
};
|
||||
export const match = path => {
|
||||
return router.match(path);
|
||||
};
|
||||
|
||||
runInDebug(() => {
|
||||
window.DataSourceRoutes = () => {
|
||||
// debug time only way to access the application and be able to lookup
|
||||
// services, don't use ConsulUi global elsewhere!
|
||||
const container = window.ConsulUi.__container__.lookup('service:container');
|
||||
const win = window.open('', '_blank');
|
||||
win.document.write(`
|
||||
<body>
|
||||
<pre>
|
||||
${Object.entries(routes)
|
||||
.map(([key, value]) => {
|
||||
let cls = container
|
||||
.keyForClass(value.cls)
|
||||
.split('/')
|
||||
.pop();
|
||||
cls = cls
|
||||
.split('-')
|
||||
.map(item => `${item[0].toUpperCase()}${item.substr(1)}`)
|
||||
.join('');
|
||||
return `${key}
|
||||
${cls}Repository.${value.method}(params)
|
||||
|
||||
`;
|
||||
})
|
||||
.join('')}
|
||||
</pre>
|
||||
</body>
|
||||
`);
|
||||
win.focus();
|
||||
return;
|
||||
};
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
import { runInDebug } from '@ember/debug';
|
||||
|
||||
export default {
|
||||
name: 'container',
|
||||
initialize(application) {
|
||||
const container = application.lookup('service:container');
|
||||
// find all the services and add their classes to the container so we can
|
||||
// look instances up by class afterwards as we then resolve the
|
||||
// registration for each of these further down this means that any top
|
||||
// level code for these services is executed, this is most useful for
|
||||
// making sure any annotation type decorators are executed.
|
||||
// For now we only want repositories, so only look for those for the moment
|
||||
let repositories = container
|
||||
.get('container-debug-adapter:main')
|
||||
.catalogEntriesByType('service')
|
||||
.filter(item => item.startsWith('repository/'));
|
||||
|
||||
// during testing we get -test files in here, filter those out but only in debug envs
|
||||
runInDebug(() => (repositories = repositories.filter(item => !item.endsWith('-test'))));
|
||||
|
||||
// 'service' service is not returned by catalogEntriesByType, possibly
|
||||
// related to pods and the service being called 'service':
|
||||
// https://github.com/ember-cli/ember-resolver/blob/c07287af17766bfd3acf390f867fea17686f77d2/addon/resolvers/classic/container-debug-adapter.js#L80
|
||||
// so push it on the end
|
||||
repositories.push('repository/service');
|
||||
//
|
||||
repositories.forEach(item => {
|
||||
const key = `service:${item}`;
|
||||
container.set(key, container.resolveRegistration(key));
|
||||
});
|
||||
},
|
||||
};
|
|
@ -8,11 +8,11 @@ export default Mixin.create(WithBlockingActions, {
|
|||
actions: {
|
||||
use: function(item) {
|
||||
return this.repo
|
||||
.findBySlug(
|
||||
get(item, 'AccessorID'),
|
||||
this.modelFor('dc').dc.Name,
|
||||
this.modelFor('nspace').nspace.substr(1)
|
||||
)
|
||||
.findBySlug({
|
||||
ns: this.modelFor('nspace').nspace.substr(1),
|
||||
dc: this.modelFor('dc').dc.Name,
|
||||
id: get(item, 'AccessorID'),
|
||||
})
|
||||
.then(item => {
|
||||
return this.settings.persist({
|
||||
token: {
|
||||
|
|
|
@ -43,7 +43,10 @@ export default class DcRoute extends Route {
|
|||
app.nspaces.length > 1 ? findActiveNspace(app.nspaces, nspace) : app.nspaces.firstObject;
|
||||
|
||||
// When disabled nspaces is [], so nspace is undefined
|
||||
const permissions = await this.permissionsRepo.findAll(params.dc, get(nspace || {}, 'Name'));
|
||||
const permissions = await this.permissionsRepo.findAll({
|
||||
dc: params.dc,
|
||||
nspace: get(nspace || {}, 'Name'),
|
||||
});
|
||||
return {
|
||||
dc,
|
||||
nspace,
|
||||
|
@ -79,7 +82,10 @@ export default class DcRoute extends Route {
|
|||
const controller = this.controllerFor('application');
|
||||
Promise.all([
|
||||
this.nspacesRepo.findAll(),
|
||||
this.permissionsRepo.findAll(get(controller, 'dc.Name'), get(controller, 'nspace.Name')),
|
||||
this.permissionsRepo.findAll({
|
||||
dc: get(controller, 'dc.Name'),
|
||||
nspace: get(controller, 'nspace.Name'),
|
||||
}),
|
||||
]).then(([nspaces, permissions]) => {
|
||||
if (typeof controller !== 'undefined') {
|
||||
controller.setProperties({
|
||||
|
|
|
@ -22,10 +22,10 @@ export default class IndexRoute extends Route {
|
|||
model(params) {
|
||||
return hash({
|
||||
...this.repo.status({
|
||||
items: this.repo.findAllByDatacenter(
|
||||
this.modelFor('dc').dc.Name,
|
||||
this.modelFor('nspace').nspace.substr(1)
|
||||
),
|
||||
items: this.repo.findAllByDatacenter({
|
||||
dc: this.modelFor('dc').dc.Name,
|
||||
ns: this.modelFor('nspace').nspace.substr(1),
|
||||
}),
|
||||
}),
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
});
|
||||
|
|
|
@ -13,7 +13,10 @@ export default class EditRoute extends Route.extend(WithAclActions) {
|
|||
|
||||
model(params) {
|
||||
return hash({
|
||||
item: this.repo.findBySlug(params.id, this.modelFor('dc').dc.Name),
|
||||
item: this.repo.findBySlug({
|
||||
dc: this.modelFor('dc').dc.Name,
|
||||
id: params.id,
|
||||
}),
|
||||
types: ['management', 'client'],
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ export default class IndexRoute extends Route.extend(WithAclActions) {
|
|||
}
|
||||
|
||||
async model(params) {
|
||||
const _items = this.repo.findAllByDatacenter(this.modelFor('dc').dc.Name);
|
||||
const _items = this.repo.findAllByDatacenter({ dc: this.modelFor('dc').dc.Name });
|
||||
const _token = this.settings.findBySlug('token');
|
||||
return {
|
||||
items: await _items,
|
||||
|
|
|
@ -21,15 +21,21 @@ export default class EditRoute extends SingleRoute.extend(WithPolicyActions) {
|
|||
...model,
|
||||
...{
|
||||
routeName: this.routeName,
|
||||
items: tokenRepo.findByPolicy(get(model.item, 'ID'), dc, nspace).catch(function(e) {
|
||||
switch (get(e, 'errors.firstObject.status')) {
|
||||
case '403':
|
||||
case '401':
|
||||
// do nothing the SingleRoute will have caught it already
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}),
|
||||
items: tokenRepo
|
||||
.findByPolicy({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: get(model.item, 'ID'),
|
||||
})
|
||||
.catch(function(e) {
|
||||
switch (get(e, 'errors.firstObject.status')) {
|
||||
case '403':
|
||||
case '401':
|
||||
// do nothing the SingleRoute will have caught it already
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -26,10 +26,10 @@ export default class IndexRoute extends Route.extend(WithPolicyActions) {
|
|||
model(params) {
|
||||
return hash({
|
||||
...this.repo.status({
|
||||
items: this.repo.findAllByDatacenter(
|
||||
this.modelFor('dc').dc.Name,
|
||||
this.modelFor('nspace').nspace.substr(1)
|
||||
),
|
||||
items: this.repo.findAllByDatacenter({
|
||||
ns: this.modelFor('nspace').nspace.substr(1),
|
||||
dc: this.modelFor('dc').dc.Name,
|
||||
}),
|
||||
}),
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
});
|
||||
|
|
|
@ -20,15 +20,21 @@ export default class EditRoute extends SingleRoute.extend(WithRoleActions) {
|
|||
return hash({
|
||||
...model,
|
||||
...{
|
||||
items: tokenRepo.findByRole(get(model.item, 'ID'), dc, nspace).catch(function(e) {
|
||||
switch (get(e, 'errors.firstObject.status')) {
|
||||
case '403':
|
||||
case '401':
|
||||
// do nothing the SingleRoute will have caught it already
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}),
|
||||
items: tokenRepo
|
||||
.findByRole({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: get(model.item, 'ID'),
|
||||
})
|
||||
.catch(function(e) {
|
||||
switch (get(e, 'errors.firstObject.status')) {
|
||||
case '403':
|
||||
case '401':
|
||||
// do nothing the SingleRoute will have caught it already
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,10 +22,10 @@ export default class IndexRoute extends Route.extend(WithRoleActions) {
|
|||
model(params) {
|
||||
return hash({
|
||||
...this.repo.status({
|
||||
items: this.repo.findAllByDatacenter(
|
||||
this.modelFor('dc').dc.Name,
|
||||
this.modelFor('nspace').nspace.substr(1)
|
||||
),
|
||||
items: this.repo.findAllByDatacenter({
|
||||
ns: this.modelFor('nspace').nspace.substr(1),
|
||||
dc: this.modelFor('dc').dc.Name,
|
||||
}),
|
||||
}),
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
});
|
||||
|
|
|
@ -35,10 +35,10 @@ export default class IndexRoute extends Route.extend(WithTokenActions) {
|
|||
model(params) {
|
||||
return hash({
|
||||
...this.repo.status({
|
||||
items: this.repo.findAllByDatacenter(
|
||||
this.modelFor('dc').dc.Name,
|
||||
this.modelFor('nspace').nspace.substr(1)
|
||||
),
|
||||
items: this.repo.findAllByDatacenter({
|
||||
ns: this.modelFor('nspace').nspace.substr(1),
|
||||
dc: this.modelFor('dc').dc.Name,
|
||||
}),
|
||||
}),
|
||||
nspace: this.modelFor('nspace').nspace.substr(1),
|
||||
token: this.settings.findBySlug('token'),
|
||||
|
|
|
@ -11,7 +11,11 @@ export default class EditRoute extends Route {
|
|||
|
||||
let item;
|
||||
if (typeof intention_id !== 'undefined') {
|
||||
item = await this.repo.findBySlug(intention_id, dc, nspace);
|
||||
item = await this.repo.findBySlug({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: intention_id,
|
||||
});
|
||||
} else {
|
||||
const defaultNspace = this.env.var('CONSUL_NSPACES_ENABLED') ? '*' : 'default';
|
||||
item = await this.repo.create({
|
||||
|
|
|
@ -24,14 +24,26 @@ export default class EditRoute extends Route {
|
|||
nspace: nspace || 'default',
|
||||
parent:
|
||||
typeof key !== 'undefined'
|
||||
? this.repo.findBySlug(ascend(key, 1) || '/', dc, nspace)
|
||||
: this.repo.findBySlug('/', dc, nspace),
|
||||
? this.repo.findBySlug({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: ascend(key, 1) || '/',
|
||||
})
|
||||
: this.repo.findBySlug({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: '/',
|
||||
}),
|
||||
item: create
|
||||
? this.repo.create({
|
||||
Datacenter: dc,
|
||||
Namespace: nspace,
|
||||
})
|
||||
: this.repo.findBySlug(key, dc, nspace),
|
||||
: this.repo.findBySlug({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: key,
|
||||
}),
|
||||
session: null,
|
||||
}).then(model => {
|
||||
// TODO: Consider loading this after initial page load
|
||||
|
@ -41,7 +53,11 @@ export default class EditRoute extends Route {
|
|||
return hash({
|
||||
...model,
|
||||
...{
|
||||
session: this.sessionRepo.findByKey(session, dc, nspace),
|
||||
session: this.sessionRepo.findByKey({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: session,
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -31,12 +31,30 @@ export default class IndexRoute extends Route {
|
|||
const dc = this.modelFor('dc').dc.Name;
|
||||
const nspace = this.modelFor('nspace').nspace.substr(1);
|
||||
return hash({
|
||||
parent: this.repo.findBySlug(key, dc, nspace),
|
||||
parent: this.repo.findBySlug({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: key,
|
||||
}),
|
||||
}).then(model => {
|
||||
return hash({
|
||||
...model,
|
||||
...{
|
||||
items: this.repo.findAllBySlug(get(model.parent, 'Key'), dc, nspace),
|
||||
items: this.repo
|
||||
.findAllBySlug({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: get(model.parent, 'Key'),
|
||||
})
|
||||
.catch(e => {
|
||||
const status = get(e, 'errors.firstObject.status');
|
||||
switch (status) {
|
||||
case '403':
|
||||
return this.transitionTo('dc.acls.tokens');
|
||||
default:
|
||||
return this.transitionTo('dc.kv.index');
|
||||
}
|
||||
}),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -28,7 +28,7 @@ export default class EditRoute extends Route.extend(WithNspaceActions) {
|
|||
},
|
||||
})
|
||||
)
|
||||
: repo.findBySlug(params.name),
|
||||
: repo.findBySlug({ id: params.name }),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,11 @@ export default Route.extend({
|
|||
Namespace: nspace,
|
||||
})
|
||||
)
|
||||
: repo.findBySlug(params.id, dc, nspace),
|
||||
: repo.findBySlug({
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
id: params.id,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import Service from '@ember/service';
|
||||
|
||||
export default class ContainerService extends Service {
|
||||
constructor(owner) {
|
||||
super(...arguments);
|
||||
this._owner = owner;
|
||||
this._wm = new WeakMap();
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
this._wm.set(value, key);
|
||||
}
|
||||
|
||||
// vaguely private, used publicly for debugging purposes
|
||||
keyForClass(cls) {
|
||||
return this._wm.get(cls);
|
||||
}
|
||||
|
||||
get(key) {
|
||||
if (typeof key !== 'string') {
|
||||
key = this.keyForClass(key);
|
||||
}
|
||||
return this.lookup(key);
|
||||
}
|
||||
|
||||
lookup(key) {
|
||||
return this._owner.lookup(key);
|
||||
}
|
||||
|
||||
resolveRegistration(key) {
|
||||
// ember resolveRegistration returns an ember flavoured class extending
|
||||
// from the actual class, access the actual class from the
|
||||
// prototype/parent which is what decorators pass through as target
|
||||
return this._owner.resolveRegistration(key).prototype;
|
||||
}
|
||||
}
|
|
@ -1,95 +1,28 @@
|
|||
import Service, { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { match } from 'consul-ui/decorators/data-source';
|
||||
import { singularize } from 'ember-inflector';
|
||||
|
||||
export default class HttpService extends Service {
|
||||
@service('repository/dc')
|
||||
datacenters;
|
||||
@service('repository/dc') datacenters;
|
||||
@service('repository/node') leader;
|
||||
@service('repository/service') gateways;
|
||||
@service('repository/service-instance') 'proxy-service-instance';
|
||||
@service('repository/proxy') 'proxy-instance';
|
||||
@service('repository/nspace') namespaces;
|
||||
@service('repository/metrics') metrics;
|
||||
@service('repository/oidc-provider') oidc;
|
||||
|
||||
@service('repository/node')
|
||||
nodes;
|
||||
|
||||
@service('repository/node')
|
||||
node;
|
||||
|
||||
@service('repository/node')
|
||||
leader;
|
||||
|
||||
@service('repository/service')
|
||||
gateways;
|
||||
|
||||
@service('repository/service')
|
||||
services;
|
||||
|
||||
@service('repository/service')
|
||||
service;
|
||||
|
||||
@service('repository/service-instance')
|
||||
'service-instance';
|
||||
|
||||
@service('repository/service-instance')
|
||||
'proxy-service-instance';
|
||||
|
||||
@service('repository/service-instance')
|
||||
'service-instances';
|
||||
|
||||
@service('repository/proxy')
|
||||
proxies;
|
||||
|
||||
@service('repository/proxy')
|
||||
'proxy-instance';
|
||||
|
||||
@service('repository/discovery-chain')
|
||||
'discovery-chain';
|
||||
|
||||
@service('repository/topology')
|
||||
topology;
|
||||
|
||||
@service('repository/coordinate')
|
||||
coordinates;
|
||||
|
||||
@service('repository/session')
|
||||
sessions;
|
||||
|
||||
@service('repository/nspace')
|
||||
namespaces;
|
||||
|
||||
@service('repository/intention')
|
||||
intentions;
|
||||
|
||||
@service('repository/intention')
|
||||
intention;
|
||||
|
||||
@service('repository/kv')
|
||||
kv;
|
||||
|
||||
@service('repository/token')
|
||||
token;
|
||||
|
||||
@service('repository/policy')
|
||||
policies;
|
||||
|
||||
@service('repository/policy')
|
||||
policy;
|
||||
|
||||
@service('repository/role')
|
||||
roles;
|
||||
|
||||
@service('repository/oidc-provider')
|
||||
oidc;
|
||||
|
||||
@service('repository/metrics')
|
||||
metrics;
|
||||
|
||||
@service('data-source/protocols/http/blocking')
|
||||
type;
|
||||
@service('data-source/protocols/http/blocking') type;
|
||||
|
||||
source(src, configuration) {
|
||||
// TODO: Consider adding/requiring 'action': nspace, dc, model, action, ...rest
|
||||
const [, nspace, dc, model, ...rest] = src.split('/').map(decodeURIComponent);
|
||||
// nspaces can be filled, blank or *
|
||||
// so we might get urls like //dc/services
|
||||
let find;
|
||||
const repo = this[model];
|
||||
const [, , , model] = src.split('/');
|
||||
const owner = getOwner(this);
|
||||
const route = match(src);
|
||||
const find = route.cb(route.params, owner);
|
||||
|
||||
const repo = this[model] || owner.lookup(`service:repository/${singularize(model)}`);
|
||||
configuration.createEvent = function(result = {}, configuration) {
|
||||
const event = {
|
||||
type: 'message',
|
||||
|
@ -101,141 +34,6 @@ export default class HttpService extends Service {
|
|||
}
|
||||
return event;
|
||||
};
|
||||
let method, slug, more, protocol;
|
||||
switch (model) {
|
||||
case 'metrics':
|
||||
[method, slug, ...more] = rest;
|
||||
switch (method) {
|
||||
case 'summary-for-service':
|
||||
[protocol, ...more] = more;
|
||||
find = configuration =>
|
||||
repo.findServiceSummary(protocol, slug, dc, nspace, configuration);
|
||||
break;
|
||||
case 'upstream-summary-for-service':
|
||||
find = configuration => repo.findUpstreamSummary(slug, dc, nspace, configuration);
|
||||
break;
|
||||
case 'downstream-summary-for-service':
|
||||
find = configuration => repo.findDownstreamSummary(slug, dc, nspace, configuration);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'datacenters':
|
||||
case 'namespaces':
|
||||
find = configuration => repo.findAll(configuration);
|
||||
break;
|
||||
case 'services':
|
||||
case 'nodes':
|
||||
case 'roles':
|
||||
case 'policies':
|
||||
find = configuration => repo.findAllByDatacenter(dc, nspace, configuration);
|
||||
break;
|
||||
case 'leader':
|
||||
find = configuration => repo.findLeader(dc, configuration);
|
||||
break;
|
||||
case 'intentions':
|
||||
[method, ...slug] = rest;
|
||||
switch (method) {
|
||||
case 'for-service':
|
||||
find = configuration => repo.findByService(slug, dc, nspace, configuration);
|
||||
break;
|
||||
default:
|
||||
find = configuration => repo.findAllByDatacenter(dc, nspace, configuration);
|
||||
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) {
|
||||
case 'for-node':
|
||||
find = configuration => repo.findAllByNode(slug, dc, configuration);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'proxies':
|
||||
[method, ...slug] = rest;
|
||||
switch (method) {
|
||||
case 'for-service':
|
||||
find = configuration => repo.findAllBySlug(slug, dc, nspace, configuration);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'gateways':
|
||||
[method, ...slug] = rest;
|
||||
switch (method) {
|
||||
case 'for-service':
|
||||
find = configuration => repo.findGatewayBySlug(slug, dc, nspace, configuration);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'sessions':
|
||||
[method, ...slug] = rest;
|
||||
switch (method) {
|
||||
case 'for-node':
|
||||
find = configuration => repo.findByNode(slug, dc, nspace, configuration);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'token':
|
||||
find = configuration => repo.self(rest[1], dc);
|
||||
break;
|
||||
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-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 =>
|
||||
repo.findInstanceBySlug(rest[0], rest[1], rest[2], dc, nspace, configuration);
|
||||
break;
|
||||
case 'topology':
|
||||
// id, service kind
|
||||
find = configuration => repo.findBySlug(rest[0], rest[1], dc, nspace, configuration);
|
||||
break;
|
||||
case 'policy':
|
||||
case 'kv':
|
||||
case 'intention':
|
||||
slug = rest[0];
|
||||
if (slug) {
|
||||
find = configuration => repo.findBySlug(slug, dc, nspace, configuration);
|
||||
} else {
|
||||
find = configuration =>
|
||||
Promise.resolve(repo.create({ Datacenter: dc, Namespace: nspace }));
|
||||
}
|
||||
break;
|
||||
case 'oidc':
|
||||
[method, ...slug] = rest;
|
||||
switch (method) {
|
||||
case 'providers':
|
||||
find = configuration => repo.findAllByDatacenter(dc, nspace, configuration);
|
||||
break;
|
||||
case 'provider':
|
||||
find = configuration => repo.findBySlug(slug[0], dc, nspace);
|
||||
break;
|
||||
case 'authorize':
|
||||
find = configuration =>
|
||||
repo.authorize(slug[0], slug[1], slug[2], dc, nspace, configuration);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return this.type.source(find, configuration);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,43 +23,33 @@ export default class RepositoryService extends Service {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a set of permissions base don a slug, loads in the access
|
||||
* permissions for themand checks/validates
|
||||
* Creates a set of permissions based on an id/slug, loads in the access
|
||||
* permissions for them and checks/validates
|
||||
*/
|
||||
async authorizeBySlug(cb, access, slug, dc, nspace) {
|
||||
return this.validatePermissions(
|
||||
cb,
|
||||
await this.permissions.findBySlug(slug, this.getModelName(), dc, nspace),
|
||||
access,
|
||||
dc,
|
||||
nspace
|
||||
);
|
||||
async authorizeBySlug(cb, access, params) {
|
||||
params.resources = await this.permissions.findBySlug(params, this.getModelName());
|
||||
return this.validatePermissions(cb, access, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads in the access permissions and checks/validates them for a set of
|
||||
* permissions
|
||||
*/
|
||||
async authorizeByPermissions(cb, permissions, access, dc, nspace) {
|
||||
return this.validatePermissions(
|
||||
cb,
|
||||
await this.permissions.authorize(permissions, dc, nspace),
|
||||
access,
|
||||
dc,
|
||||
nspace
|
||||
);
|
||||
async authorizeByPermissions(cb, access, params) {
|
||||
params.resources = await this.permissions.authorize(params);
|
||||
return this.validatePermissions(cb, access, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks already loaded permissions for certain access before calling cb to
|
||||
* return the thing you wanted to check the permissions on
|
||||
*/
|
||||
async validatePermissions(cb, permissions, access, dc, nspace) {
|
||||
async validatePermissions(cb, access, params) {
|
||||
// inspect the permissions for this segment/slug remotely, if we have zero
|
||||
// permissions fire a fake 403 so we don't even request the model/resource
|
||||
if (permissions.length > 0) {
|
||||
const permission = permissions.find(item => item.Access === access);
|
||||
if (permission && permission.Allow === false) {
|
||||
if (params.resources.length > 0) {
|
||||
const resource = params.resources.find(item => item.Access === access);
|
||||
if (resource && resource.Allow === false) {
|
||||
// TODO: Here we temporarily make a hybrid HTTPError/ember-data HTTP error
|
||||
// we should eventually use HTTPError's everywhere
|
||||
const e = new HTTPError(403);
|
||||
|
@ -71,7 +61,7 @@ export default class RepositoryService extends Service {
|
|||
// add the `Resource` information to the record/model so we can inspect
|
||||
// them in other places like templates etc
|
||||
if (get(item, 'Resources')) {
|
||||
set(item, 'Resources', permissions);
|
||||
set(item, 'Resources', params.resources);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
@ -102,34 +92,29 @@ export default class RepositoryService extends Service {
|
|||
return this.store.peekRecord(this.getModelName(), id);
|
||||
}
|
||||
|
||||
findAllByDatacenter(dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
};
|
||||
findAllByDatacenter(params, configuration = {}) {
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.store.query(this.getModelName(), query);
|
||||
return this.store.query(this.getModelName(), params);
|
||||
}
|
||||
|
||||
async findBySlug(slug, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
id: slug,
|
||||
};
|
||||
async findBySlug(params, configuration = {}) {
|
||||
if (params.id === '') {
|
||||
return this.create({
|
||||
Datacenter: params.dc,
|
||||
Namespace: params.ns,
|
||||
});
|
||||
}
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.authorizeBySlug(
|
||||
() => this.store.queryRecord(this.getModelName(), query),
|
||||
() => this.store.queryRecord(this.getModelName(), params),
|
||||
ACCESS_READ,
|
||||
slug,
|
||||
dc,
|
||||
nspace
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import RepositoryService from 'consul-ui/services/repository';
|
|||
import statusFactory from 'consul-ui/utils/acls-status';
|
||||
import isValidServerErrorFactory from 'consul-ui/utils/http/acl/is-valid-server-error';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/auth-method';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const isValidServerError = isValidServerErrorFactory();
|
||||
const status = statusFactory(isValidServerError, Promise);
|
||||
|
@ -20,6 +21,16 @@ export default class AuthMethodService extends RepositoryService {
|
|||
return SLUG_KEY;
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/auth-methods')
|
||||
async findAllByDatacenter() {
|
||||
return super.findAllByDatacenter(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/auth-method/:id')
|
||||
async findBySlug() {
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
|
||||
status(obj) {
|
||||
return status(obj);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import RepositoryService from 'consul-ui/services/repository';
|
|||
import tomographyFactory from 'consul-ui/utils/tomography';
|
||||
import distance from 'consul-ui/utils/distance';
|
||||
const tomography = tomographyFactory(distance);
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'coordinate';
|
||||
export default class CoordinateService extends RepositoryService {
|
||||
|
@ -13,25 +14,21 @@ export default class CoordinateService extends RepositoryService {
|
|||
|
||||
// Coordinates don't need nspaces so we have a custom method here
|
||||
// that doesn't accept nspaces
|
||||
findAllByDatacenter(dc, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
};
|
||||
@dataSource('/:ns/:dc/coordinates')
|
||||
findAllByDatacenter(params, configuration = {}) {
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.store.query(this.getModelName(), query);
|
||||
return this.store.query(this.getModelName(), params);
|
||||
}
|
||||
|
||||
findAllByNode(node, dc, configuration) {
|
||||
return this.findAllByDatacenter(dc, configuration).then(function(coordinates) {
|
||||
@dataSource('/:ns/:dc/coordinates/for-node/:id')
|
||||
findAllByNode(params, configuration) {
|
||||
return this.findAllByDatacenter(params, configuration).then(function(coordinates) {
|
||||
let results = {};
|
||||
if (get(coordinates, 'length') > 1) {
|
||||
results = tomography(
|
||||
node,
|
||||
coordinates
|
||||
);
|
||||
results = tomography(params.id, coordinates);
|
||||
}
|
||||
results.meta = get(coordinates, 'meta');
|
||||
return results;
|
||||
|
|
|
@ -2,6 +2,7 @@ import { inject as service } from '@ember/service';
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import { get } from '@ember/object';
|
||||
import Error from '@ember/error';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'dc';
|
||||
export default class DcService extends RepositoryService {
|
||||
|
@ -12,7 +13,8 @@ export default class DcService extends RepositoryService {
|
|||
return modelName;
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
@dataSource('/:ns/:dc/datacenters')
|
||||
async findAll(params, configuration = {}) {
|
||||
return this.store.query(this.getModelName(), {});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import { get, set } from '@ember/object';
|
||||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'discovery-chain';
|
||||
const ERROR_MESH_DISABLED = 'Connect must be enabled in order to use this endpoint';
|
||||
|
@ -12,8 +13,9 @@ export default class DiscoveryChainService extends RepositoryService {
|
|||
return modelName;
|
||||
}
|
||||
|
||||
findBySlug(slug, dc, nspace, configuration = {}) {
|
||||
const datacenter = this.dcs.peekOne(dc);
|
||||
@dataSource('/:ns/:dc/discovery-chain/:id')
|
||||
findBySlug(params, configuration = {}) {
|
||||
const datacenter = this.dcs.peekOne(params.dc);
|
||||
if (datacenter !== null && !get(datacenter, 'MeshEnabled')) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { set, get } from '@ember/object';
|
||||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import { PRIMARY_KEY } from 'consul-ui/models/intention';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'intention';
|
||||
export default class IntentionRepository extends RepositoryService {
|
||||
|
@ -34,13 +35,13 @@ export default class IntentionRepository extends RepositoryService {
|
|||
|
||||
// legacy intentions are strange that in order to read/write you need access
|
||||
// to either/or the destination or source
|
||||
async authorizeBySlug(cb, access, slug, dc, nspace) {
|
||||
const [, source, , destination] = slug.split(':');
|
||||
async authorizeBySlug(cb, access, params) {
|
||||
const [, source, , destination] = params.id.split(':');
|
||||
const ability = this.permissions.abilityFor(this.getModelName());
|
||||
const permissions = ability
|
||||
params.resources = ability
|
||||
.generateForSegment(source)
|
||||
.concat(ability.generateForSegment(destination));
|
||||
return this.authorizeByPermissions(cb, permissions, access, dc, nspace);
|
||||
return this.authorizeByPermissions(cb, access, params);
|
||||
}
|
||||
|
||||
async persist(obj) {
|
||||
|
@ -56,11 +57,22 @@ export default class IntentionRepository extends RepositoryService {
|
|||
return res;
|
||||
}
|
||||
|
||||
async findByService(slug, dc, nspace, configuration = {}) {
|
||||
@dataSource('/:ns/:dc/intentions')
|
||||
async findAllByDatacenter() {
|
||||
return super.findAllByDatacenter(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/intention/:id')
|
||||
async findBySlug() {
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/intentions/for-service/:id')
|
||||
async findByService(params, configuration = {}) {
|
||||
const query = {
|
||||
dc,
|
||||
nspace,
|
||||
filter: `SourceName == "${slug}" or DestinationName == "${slug}" or SourceName == "*" or DestinationName == "*"`,
|
||||
dc: params.dc,
|
||||
nspace: params.nspace,
|
||||
filter: `SourceName == "${params.id}" or DestinationName == "${params.id}" or SourceName == "*" or DestinationName == "*"`,
|
||||
};
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
|
|
|
@ -3,6 +3,7 @@ import isFolder from 'consul-ui/utils/isFolder';
|
|||
import { get } from '@ember/object';
|
||||
import { PRIMARY_KEY } from 'consul-ui/models/kv';
|
||||
import { ACCESS_LIST } from 'consul-ui/abilities/base';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'kv';
|
||||
export default class KvService extends RepositoryService {
|
||||
|
@ -15,71 +16,65 @@ export default class KvService extends RepositoryService {
|
|||
}
|
||||
|
||||
// this one gives you the full object so key,values and meta
|
||||
async findBySlug(slug, dc, nspace, configuration = {}) {
|
||||
if (isFolder(slug)) {
|
||||
@dataSource('/:ns/:dc/kv/*id')
|
||||
async findBySlug(params, configuration = {}) {
|
||||
if (isFolder(params.id)) {
|
||||
// we only use findBySlug for a folder when we are looking to create a
|
||||
// parent for a key for retriveing something Model shaped. Therefore we
|
||||
// only use existing records or a fake record with the correct Key,
|
||||
// which means we don't need to inpsect permissions as its an already
|
||||
// which means we don't need to inspect permissions as its an already
|
||||
// existing KV or a fake one
|
||||
|
||||
// TODO: This very much shouldn't be here,
|
||||
// needs to eventually use ember-datas generateId thing
|
||||
// in the meantime at least our fingerprinter
|
||||
const id = JSON.stringify([nspace, dc, slug]);
|
||||
let item = this.store.peekRecord(this.getModelName(), id);
|
||||
const uid = JSON.stringify([params.ns, params.dc, params.id]);
|
||||
let item = this.store.peekRecord(this.getModelName(), uid);
|
||||
if (!item) {
|
||||
item = this.create({
|
||||
Key: slug,
|
||||
Datacenter: dc,
|
||||
Namespace: nspace,
|
||||
Key: params.id,
|
||||
Datacenter: params.dc,
|
||||
Namespace: params.ns,
|
||||
});
|
||||
}
|
||||
return item;
|
||||
} else {
|
||||
return super.findBySlug(slug, dc, nspace, configuration);
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
// this one only gives you keys
|
||||
// https://www.consul.io/api/kv.html
|
||||
findAllBySlug(key, dc, nspace, configuration = {}) {
|
||||
if (key === '/') {
|
||||
key = '';
|
||||
findAllBySlug(params, configuration = {}) {
|
||||
if (params.id === '/') {
|
||||
params.id = '';
|
||||
}
|
||||
return this.authorizeBySlug(
|
||||
async () => {
|
||||
const query = {
|
||||
id: key,
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
separator: '/',
|
||||
};
|
||||
params.separator = '/';
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
params.index = configuration.cursor;
|
||||
}
|
||||
let items;
|
||||
try {
|
||||
items = await this.store.query(this.getModelName(), query);
|
||||
items = await this.store.query(this.getModelName(), params);
|
||||
} catch (e) {
|
||||
if (get(e, 'errors.firstObject.status') === '404') {
|
||||
// TODO: This very much shouldn't be here,
|
||||
// needs to eventually use ember-datas generateId thing
|
||||
// in the meantime at least our fingerprinter
|
||||
const id = JSON.stringify([dc, key]);
|
||||
const record = this.store.peekRecord(this.getModelName(), id);
|
||||
const uid = JSON.stringify([params.ns, params.dc, params.id]);
|
||||
const record = this.store.peekRecord(this.getModelName(), uid);
|
||||
if (record) {
|
||||
record.unloadRecord();
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return items.filter(item => key !== get(item, 'Key'));
|
||||
return items.filter(item => params.id !== get(item, 'Key'));
|
||||
},
|
||||
ACCESS_LIST,
|
||||
key,
|
||||
dc,
|
||||
nspace
|
||||
params
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
// CONSUL_METRICS_POLL_INTERVAL controls how long between each poll to the
|
||||
// metrics provider
|
||||
|
||||
export default class MetricsService extends RepositoryService {
|
||||
@service('ui-config') config;
|
||||
@service('env') env;
|
||||
|
@ -11,6 +11,10 @@ export default class MetricsService extends RepositoryService {
|
|||
|
||||
error = null;
|
||||
|
||||
getModelName() {
|
||||
return 'metrics';
|
||||
}
|
||||
|
||||
init() {
|
||||
super.init(...arguments);
|
||||
const config = this.config.get();
|
||||
|
@ -34,13 +38,26 @@ export default class MetricsService extends RepositoryService {
|
|||
}
|
||||
}
|
||||
|
||||
findServiceSummary(protocol, slug, dc, nspace, configuration = {}) {
|
||||
@dataSource('/:ns/:dc/metrics/summary-for-service/:slug/:protocol')
|
||||
findServiceSummary(params, configuration = {}) {
|
||||
if (this.error) {
|
||||
return Promise.reject(this.error);
|
||||
}
|
||||
const promises = [
|
||||
this.provider.serviceRecentSummarySeries(slug, dc, nspace, protocol, {}),
|
||||
this.provider.serviceRecentSummaryStats(slug, dc, nspace, protocol, {}),
|
||||
this.provider.serviceRecentSummarySeries(
|
||||
params.slug,
|
||||
params.dc,
|
||||
params.ns,
|
||||
params.protocol,
|
||||
{}
|
||||
),
|
||||
this.provider.serviceRecentSummaryStats(
|
||||
params.slug,
|
||||
params.dc,
|
||||
params.ns,
|
||||
params.protocol,
|
||||
{}
|
||||
),
|
||||
];
|
||||
return Promise.all(promises).then(results => {
|
||||
return {
|
||||
|
@ -53,27 +70,33 @@ export default class MetricsService extends RepositoryService {
|
|||
});
|
||||
}
|
||||
|
||||
findUpstreamSummary(slug, dc, nspace, configuration = {}) {
|
||||
@dataSource('/:ns/:dc/metrics/upstream-summary-for-service/:slug/:protocol')
|
||||
findUpstreamSummary(params, configuration = {}) {
|
||||
if (this.error) {
|
||||
return Promise.reject(this.error);
|
||||
}
|
||||
return this.provider.upstreamRecentSummaryStats(slug, dc, nspace, {}).then(result => {
|
||||
result.meta = {
|
||||
interval: this.env.var('CONSUL_METRICS_POLL_INTERVAL') || 10000,
|
||||
};
|
||||
return result;
|
||||
});
|
||||
return this.provider
|
||||
.upstreamRecentSummaryStats(params.slug, params.dc, params.ns, {})
|
||||
.then(result => {
|
||||
result.meta = {
|
||||
interval: this.env.var('CONSUL_METRICS_POLL_INTERVAL') || 10000,
|
||||
};
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
findDownstreamSummary(slug, dc, nspace, configuration = {}) {
|
||||
@dataSource('/:ns/:dc/metrics/downstream-summary-for-service/:slug/:protocol')
|
||||
findDownstreamSummary(params, configuration = {}) {
|
||||
if (this.error) {
|
||||
return Promise.reject(this.error);
|
||||
}
|
||||
return this.provider.downstreamRecentSummaryStats(slug, dc, nspace, {}).then(result => {
|
||||
result.meta = {
|
||||
interval: this.env.var('CONSUL_METRICS_POLL_INTERVAL') || 10000,
|
||||
};
|
||||
return result;
|
||||
});
|
||||
return this.provider
|
||||
.downstreamRecentSummaryStats(params.slug, params.dc, params.ns, {})
|
||||
.then(result => {
|
||||
result.meta = {
|
||||
interval: this.env.var('CONSUL_METRICS_POLL_INTERVAL') || 10000,
|
||||
};
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'node';
|
||||
export default class NodeService extends RepositoryService {
|
||||
|
@ -6,13 +7,21 @@ export default class NodeService extends RepositoryService {
|
|||
return modelName;
|
||||
}
|
||||
|
||||
findLeader(dc, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
};
|
||||
@dataSource('/:ns/:dc/nodes')
|
||||
async findAllByDatacenter() {
|
||||
return super.findAllByDatacenter(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/node/:id')
|
||||
async findBySlug() {
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/leader')
|
||||
findLeader(params, configuration = {}) {
|
||||
if (typeof configuration.refresh !== 'undefined') {
|
||||
query.uri = configuration.uri;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.store.queryLeader(this.getModelName(), query);
|
||||
return this.store.queryLeader(this.getModelName(), params);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/nspace';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'nspace';
|
||||
export default class NspaceService extends RepositoryService {
|
||||
|
@ -37,7 +38,13 @@ export default class NspaceService extends RepositoryService {
|
|||
return res;
|
||||
}
|
||||
|
||||
findAll(configuration = {}) {
|
||||
@dataSource('/:ns/:dc/namespace/:id')
|
||||
async findBySlug() {
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/namespaces')
|
||||
findAll(params, configuration = {}) {
|
||||
const query = {};
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
|
|
|
@ -24,7 +24,7 @@ export default class EnabledService extends RepositoryService {
|
|||
return modelName;
|
||||
}
|
||||
|
||||
findAll(configuration = {}) {
|
||||
findAll(params, configuration = {}) {
|
||||
const query = {};
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
|
|
|
@ -2,6 +2,7 @@ import { inject as service } from '@ember/service';
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { set } from '@ember/object';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'oidc-provider';
|
||||
const OAUTH_PROVIDER_NAME = 'oidc-with-url';
|
||||
|
@ -18,15 +19,19 @@ export default class OidcProviderService extends RepositoryService {
|
|||
return modelName;
|
||||
}
|
||||
|
||||
authorize(id, code, state, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
id: id,
|
||||
code: code,
|
||||
state: state,
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
};
|
||||
return this.store.authorize(this.getModelName(), query);
|
||||
@dataSource('/:ns/:dc/oidc/providers')
|
||||
async findAllByDatacenter() {
|
||||
return super.findAllByDatacenter(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/oidc/provider/:id')
|
||||
async findBySlug() {
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/oidc/authorize/:id/:code/:state')
|
||||
authorize(params, configuration = {}) {
|
||||
return this.store.authorize(this.getModelName(), params);
|
||||
}
|
||||
|
||||
logout(id, code, state, dc, nspace, configuration = {}) {
|
||||
|
|
|
@ -97,31 +97,27 @@ export default class PermissionService extends RepositoryService {
|
|||
* If ACLs are disabled, then you have access to everything, hence we check
|
||||
* that here and only make the request if ACLs are enabled
|
||||
*/
|
||||
async authorize(resources, dc, nspace) {
|
||||
async authorize(params) {
|
||||
if (!this.env.var('CONSUL_ACLS_ENABLED')) {
|
||||
return resources.map(item => {
|
||||
return params.resources.map(item => {
|
||||
return {
|
||||
...item,
|
||||
Allow: true,
|
||||
};
|
||||
});
|
||||
} else {
|
||||
let permissions = [];
|
||||
let resources = [];
|
||||
try {
|
||||
permissions = await this.store.authorize('permission', {
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
permissions: resources,
|
||||
});
|
||||
resources = await this.store.authorize('permission', params);
|
||||
} catch (e) {
|
||||
runInDebug(() => console.error(e));
|
||||
// passthrough
|
||||
}
|
||||
return permissions;
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
|
||||
async findBySlug(segment, model, dc, nspace) {
|
||||
async findBySlug(params, model) {
|
||||
let ability;
|
||||
try {
|
||||
ability = this._can.abilityFor(model);
|
||||
|
@ -129,21 +125,23 @@ export default class PermissionService extends RepositoryService {
|
|||
return [];
|
||||
}
|
||||
|
||||
const resources = ability.generateForSegment(segment.toString());
|
||||
const resources = ability.generateForSegment(params.id.toString());
|
||||
// if we get no resources for a segment it means that this
|
||||
// ability/permission isn't segmentable
|
||||
if (resources.length === 0) {
|
||||
return [];
|
||||
}
|
||||
return this.authorize(resources, dc, nspace);
|
||||
params.resources = resources;
|
||||
return this.authorize(params);
|
||||
}
|
||||
|
||||
async findByPermissions(resources, dc, nspace) {
|
||||
return this.authorize(resources, dc, nspace);
|
||||
async findByPermissions(params) {
|
||||
return this.authorize(params);
|
||||
}
|
||||
|
||||
async findAll(dc, nspace) {
|
||||
this.permissions = await this.findByPermissions(REQUIRED_PERMISSIONS, dc, nspace);
|
||||
async findAll(params) {
|
||||
params.resources = REQUIRED_PERMISSIONS;
|
||||
this.permissions = await this.findByPermissions(params);
|
||||
return this.permissions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { get } from '@ember/object';
|
|||
import statusFactory from 'consul-ui/utils/acls-status';
|
||||
import isValidServerErrorFactory from 'consul-ui/utils/http/acl/is-valid-server-error';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/policy';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const isValidServerError = isValidServerErrorFactory();
|
||||
const status = statusFactory(isValidServerError, Promise);
|
||||
|
@ -21,6 +22,16 @@ export default class PolicyService extends RepositoryService {
|
|||
return SLUG_KEY;
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/policies')
|
||||
async findAllByDatacenter() {
|
||||
return super.findAllByDatacenter(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/policy/:id')
|
||||
async findBySlug() {
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
|
||||
status(obj) {
|
||||
return status(obj);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import { PRIMARY_KEY } from 'consul-ui/models/proxy';
|
||||
import { get, set } from '@ember/object';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'proxy';
|
||||
export default class ProxyService extends RepositoryService {
|
||||
getModelName() {
|
||||
|
@ -11,17 +13,13 @@ export default class ProxyService extends RepositoryService {
|
|||
return PRIMARY_KEY;
|
||||
}
|
||||
|
||||
findAllBySlug(slug, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
id: slug,
|
||||
ns: nspace,
|
||||
dc: dc,
|
||||
};
|
||||
@dataSource('/:ns/:dc/proxies/for-service/:id')
|
||||
findAllBySlug(params, configuration = {}) {
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.store.query(this.getModelName(), query).then(items => {
|
||||
return this.store.query(this.getModelName(), params).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
|
||||
|
@ -37,17 +35,18 @@ export default class ProxyService extends RepositoryService {
|
|||
});
|
||||
}
|
||||
|
||||
findInstanceBySlug(id, node, slug, dc, nspace, configuration) {
|
||||
return this.findAllBySlug(slug, dc, nspace, configuration).then(function(items) {
|
||||
@dataSource('/:ns/:dc/proxy-instance/:serviceId/:node/:id')
|
||||
findInstanceBySlug(params, nspace, configuration) {
|
||||
return this.findAllBySlug(params, configuration).then(function(items) {
|
||||
let res = {};
|
||||
if (get(items, 'length') > 0) {
|
||||
let instance = items
|
||||
.filterBy('ServiceProxy.DestinationServiceID', id)
|
||||
.findBy('NodeName', node);
|
||||
.filterBy('ServiceProxy.DestinationServiceID', params.serviceId)
|
||||
.findBy('NodeName', params.node);
|
||||
if (instance) {
|
||||
res = instance;
|
||||
} else {
|
||||
instance = items.findBy('ServiceProxy.DestinationServiceName', slug);
|
||||
instance = items.findBy('ServiceProxy.DestinationServiceName', params.id);
|
||||
if (instance) {
|
||||
res = instance;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import RepositoryService from 'consul-ui/services/repository';
|
|||
import statusFactory from 'consul-ui/utils/acls-status';
|
||||
import isValidServerErrorFactory from 'consul-ui/utils/http/acl/is-valid-server-error';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/role';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const isValidServerError = isValidServerErrorFactory();
|
||||
const status = statusFactory(isValidServerError, Promise);
|
||||
|
@ -20,6 +21,16 @@ export default class RoleService extends RepositoryService {
|
|||
return SLUG_KEY;
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/roles')
|
||||
async findAllByDatacenter() {
|
||||
return super.findAllByDatacenter(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/role/:id')
|
||||
async findBySlug() {
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
|
||||
status(obj) {
|
||||
return status(obj);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import RepositoryService from 'consul-ui/services/repository';
|
|||
import { inject as service } from '@ember/service';
|
||||
import { set } from '@ember/object';
|
||||
import { ACCESS_READ } from 'consul-ui/abilities/base';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'service-instance';
|
||||
export default class ServiceInstanceService extends RepositoryService {
|
||||
|
@ -10,47 +11,34 @@ export default class ServiceInstanceService extends RepositoryService {
|
|||
return modelName;
|
||||
}
|
||||
|
||||
async findByService(slug, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
id: slug,
|
||||
};
|
||||
@dataSource('/:ns/:dc/service-instances/for-service/:id')
|
||||
async findByService(params, configuration = {}) {
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.authorizeBySlug(
|
||||
async () => this.store.query(this.getModelName(), query),
|
||||
async () => this.store.query(this.getModelName(), params),
|
||||
ACCESS_READ,
|
||||
slug,
|
||||
dc,
|
||||
nspace
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async findBySlug(serviceId, node, service, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
serviceId: serviceId,
|
||||
node: node,
|
||||
id: service,
|
||||
};
|
||||
@dataSource('/:ns/:dc/service-instance/:serviceId/:node/:id')
|
||||
async findBySlug(params, configuration = {}) {
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.authorizeBySlug(
|
||||
async () => this.store.queryRecord(this.getModelName(), query),
|
||||
async () => this.store.queryRecord(this.getModelName(), params),
|
||||
ACCESS_READ,
|
||||
service,
|
||||
dc,
|
||||
nspace
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async findProxyBySlug(serviceId, node, service, dc, nspace, configuration = {}) {
|
||||
@dataSource('/:ns/:dc/proxy-service-instance/:serviceId/:node/:id')
|
||||
async findProxyBySlug(params, configuration = {}) {
|
||||
const instance = await this.findBySlug(...arguments);
|
||||
let proxy = this.store.peekRecord('proxy', instance.uid);
|
||||
// Currently, we call the proxy endpoint before this endpoint
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'service';
|
||||
export default class _RepositoryService extends RepositoryService {
|
||||
export default class ServiceService extends RepositoryService {
|
||||
getModelName() {
|
||||
return modelName;
|
||||
}
|
||||
|
||||
findGatewayBySlug(slug, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
gateway: slug,
|
||||
};
|
||||
@dataSource('/:ns/:dc/services')
|
||||
async findAllByDatacenter() {
|
||||
return super.findAllByDatacenter(...arguments);
|
||||
}
|
||||
|
||||
@dataSource('/:ns/:dc/gateways/for-service/:gateway')
|
||||
findGatewayBySlug(params, configuration = {}) {
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.store.query(this.getModelName(), query);
|
||||
return this.store.query(this.getModelName(), params);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'session';
|
||||
export default class SessionService extends RepositoryService {
|
||||
|
@ -10,21 +11,18 @@ export default class SessionService extends RepositoryService {
|
|||
return modelName;
|
||||
}
|
||||
|
||||
findByNode(node, dc, nspace, configuration = {}) {
|
||||
const query = {
|
||||
id: node,
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
};
|
||||
@dataSource('/:ns/:dc/sessions/for-node/:id')
|
||||
findByNode(params, configuration = {}) {
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.store.query(this.getModelName(), query);
|
||||
return this.store.query(this.getModelName(), params);
|
||||
}
|
||||
|
||||
// TODO: Why Key? Probably should be findBySlug like the others
|
||||
findByKey(slug, dc, nspace) {
|
||||
@dataSource('/:ns/:dc/sessions/for-key/:id')
|
||||
findByKey(params, configuration = {}) {
|
||||
return this.findBySlug(...arguments);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { get } from '@ember/object';
|
|||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/token';
|
||||
import statusFactory from 'consul-ui/utils/acls-status';
|
||||
import isValidServerErrorFactory from 'consul-ui/utils/http/acl/is-valid-server-error';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const isValidServerError = isValidServerErrorFactory();
|
||||
const status = statusFactory(isValidServerError, Promise);
|
||||
|
@ -25,11 +26,13 @@ export default class TokenService extends RepositoryService {
|
|||
return status(obj);
|
||||
}
|
||||
|
||||
self(secret, dc) {
|
||||
@dataSource('/:ns/:dc/token/self/:secret')
|
||||
self(params) {
|
||||
// TODO: Does this need ns passing through?
|
||||
return this.store
|
||||
.self(this.getModelName(), {
|
||||
secret: secret,
|
||||
dc: dc,
|
||||
secret: params.secret,
|
||||
dc: params.dc,
|
||||
})
|
||||
.catch(e => {
|
||||
// If we get this 500 RPC error, it means we are a legacy ACL cluster
|
||||
|
@ -37,7 +40,7 @@ export default class TokenService extends RepositoryService {
|
|||
if (isValidServerError(e)) {
|
||||
return {
|
||||
AccessorID: null,
|
||||
SecretID: secret,
|
||||
SecretID: params.secret,
|
||||
};
|
||||
}
|
||||
return Promise.reject(e);
|
||||
|
@ -48,19 +51,19 @@ export default class TokenService extends RepositoryService {
|
|||
return this.store.clone(this.getModelName(), get(item, PRIMARY_KEY));
|
||||
}
|
||||
|
||||
findByPolicy(id, dc, nspace) {
|
||||
findByPolicy(params) {
|
||||
return this.store.query(this.getModelName(), {
|
||||
policy: id,
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
policy: params.id,
|
||||
dc: params.dc,
|
||||
ns: params.ns,
|
||||
});
|
||||
}
|
||||
|
||||
findByRole(id, dc, nspace) {
|
||||
findByRole(params) {
|
||||
return this.store.query(this.getModelName(), {
|
||||
role: id,
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
role: params.id,
|
||||
dc: params.dc,
|
||||
ns: params.ns,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import { get, set } from '@ember/object';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'topology';
|
||||
const ERROR_MESH_DISABLED = 'Connect must be enabled in order to use this endpoint';
|
||||
|
@ -13,24 +14,19 @@ export default class TopologyService extends RepositoryService {
|
|||
return modelName;
|
||||
}
|
||||
|
||||
findBySlug(slug, kind, dc, nspace, configuration = {}) {
|
||||
const datacenter = this.dcs.peekOne(dc);
|
||||
@dataSource('/:ns/:dc/topology/:id/:kind')
|
||||
findBySlug(params, configuration = {}) {
|
||||
const datacenter = this.dcs.peekOne(params.dc);
|
||||
if (datacenter !== null && !get(datacenter, 'MeshEnabled')) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const query = {
|
||||
dc: dc,
|
||||
ns: nspace,
|
||||
id: slug,
|
||||
kind: kind,
|
||||
};
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
query.index = configuration.cursor;
|
||||
query.uri = configuration.uri;
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.store.queryRecord(this.getModelName(), query).catch(e => {
|
||||
return this.store.queryRecord(this.getModelName(), params).catch(e => {
|
||||
const code = get(e, 'errors.firstObject.status');
|
||||
const body = get(e, 'errors.firstObject.detail').trim();
|
||||
const body = (get(e, 'errors.firstObject.detail') || '').trim();
|
||||
switch (code) {
|
||||
case '500':
|
||||
if (datacenter !== null && body.endsWith(ERROR_MESH_DISABLED)) {
|
||||
|
|
|
@ -160,7 +160,8 @@
|
|||
"tape": "^5.0.1",
|
||||
"text-encoding": "^0.7.0",
|
||||
"tippy.js": "^6.2.7",
|
||||
"torii": "^0.10.1"
|
||||
"torii": "^0.10.1",
|
||||
"wayfarer": "^7.0.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"ember-basic-dropdown": "^3.0.10"
|
||||
|
|
|
@ -19,7 +19,7 @@ test('findByDatacenter returns the correct data for list endpoint', function(ass
|
|||
});
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findAllByDatacenter(dc);
|
||||
return service.findAllByDatacenter({ dc });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -47,7 +47,7 @@ test('findBySlug returns the correct data for item endpoint', function(assert) {
|
|||
return stub(`/v1/acl/info/${id}?dc=${dc}`);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findBySlug(id, dc);
|
||||
return service.findBySlug({ id, dc });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -25,7 +25,10 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findAllByDatacenter(dc, nspace || undefinedNspace);
|
||||
return service.findAllByDatacenter({
|
||||
dc: dc,
|
||||
nspace: nspace || undefinedNspace,
|
||||
});
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -24,7 +24,7 @@ test('findAllByDatacenter returns the correct data for list endpoint', function(
|
|||
});
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findAllByDatacenter(dc);
|
||||
return service.findAllByDatacenter({ dc });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -51,11 +51,11 @@ test('findAllByNode calls findAllByDatacenter with the correct arguments', funct
|
|||
cursor: 1,
|
||||
};
|
||||
const service = this.subject();
|
||||
service.findAllByDatacenter = function(dc, configuration) {
|
||||
service.findAllByDatacenter = function(params, configuration) {
|
||||
assert.equal(arguments.length, 2, 'Expected to be called with the correct number of arguments');
|
||||
assert.equal(dc, datacenter);
|
||||
assert.equal(params.dc, datacenter);
|
||||
assert.deepEqual(configuration, conf);
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
return service.findAllByNode('node-name', datacenter, conf);
|
||||
return service.findAllByNode({ node: 'node-name', dc: datacenter }, conf);
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ test('findBySlug returns the correct data for item endpoint', function(assert) {
|
|||
});
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findBySlug(id, dc);
|
||||
return service.findBySlug({ id, dc });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
const result = expected(function(payload) {
|
||||
|
|
|
@ -23,7 +23,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findAllBySlug(id, dc, nspace || undefinedNspace);
|
||||
return service.findAllBySlug({ id, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -51,7 +51,7 @@ const undefinedNspace = 'default';
|
|||
return stub(`/v1/kv/${id}?dc=${dc}${typeof nspace !== 'undefined' ? `&ns=${nspace}` : ``}`);
|
||||
},
|
||||
function(service) {
|
||||
return service.findBySlug(id, dc, nspace || undefinedNspace);
|
||||
return service.findBySlug({ id, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -25,7 +25,7 @@ test('findByDatacenter returns the correct data for list endpoint', function(ass
|
|||
});
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findAllByDatacenter(dc);
|
||||
return service.findAllByDatacenter({ dc });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
actual.forEach(item => {
|
||||
|
@ -44,7 +44,7 @@ test('findBySlug returns the correct data for item endpoint', function(assert) {
|
|||
return stub(`/v1/internal/ui/node/${id}?dc=${dc}`);
|
||||
},
|
||||
function(service) {
|
||||
return service.findBySlug(id, dc);
|
||||
return service.findBySlug({ id, dc });
|
||||
},
|
||||
function(actual, expected) {
|
||||
assert.equal(actual.uid, `["${nspace}","${dc}","${actual.ID}"]`);
|
||||
|
|
|
@ -29,7 +29,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findAllByDatacenter(dc, nspace || undefinedNspace);
|
||||
return service.findAllByDatacenter({ dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -59,7 +59,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findBySlug(id, dc, nspace || undefinedNspace);
|
||||
return service.findBySlug({ id, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -30,7 +30,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findAllByDatacenter(dc, nspace || undefinedNspace);
|
||||
return service.findAllByDatacenter({ dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -61,7 +61,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findBySlug(id, dc, nspace || undefinedNspace);
|
||||
return service.findBySlug({ id, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -33,7 +33,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findGatewayBySlug(gateway, dc, nspace || undefinedNspace, conf);
|
||||
return service.findGatewayBySlug({ gateway, dc, ns: nspace || undefinedNspace }, conf);
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
const result = expected(function(payload) {
|
||||
|
|
|
@ -29,7 +29,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findByNode(id, dc, nspace || undefinedNspace);
|
||||
return service.findByNode({ id, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -59,7 +59,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function(service) {
|
||||
return service.findByKey(id, dc, nspace || undefinedNspace);
|
||||
return service.findByKey({ id, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -26,7 +26,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findAllByDatacenter(dc, nspace || undefinedNspace);
|
||||
return service.findAllByDatacenter({ dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -57,7 +57,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findBySlug(id, dc, nspace || undefinedNspace);
|
||||
return service.findBySlug({ id, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -99,7 +99,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findByPolicy(policy, dc, nspace || undefinedNspace);
|
||||
return service.findByPolicy({ id: policy, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
@ -136,7 +136,7 @@ const undefinedNspace = 'default';
|
|||
);
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findByRole(role, dc, nspace || undefinedNspace);
|
||||
return service.findByRole({ id: role, dc, ns: nspace || undefinedNspace });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -19,7 +19,7 @@ test('findBySlug returns the correct data for item endpoint', function(assert) {
|
|||
});
|
||||
},
|
||||
function performTest(service) {
|
||||
return service.findBySlug(id, kind, dc);
|
||||
return service.findBySlug({ id, kind, dc });
|
||||
},
|
||||
function performAssertion(actual, expected) {
|
||||
const result = expected(function(payload) {
|
||||
|
|
12
ui/yarn.lock
12
ui/yarn.lock
|
@ -13365,6 +13365,11 @@ nan@^2.12.1:
|
|||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
||||
|
||||
nanoassert@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/nanoassert/-/nanoassert-1.1.0.tgz#4f3152e09540fde28c76f44b19bbcd1d5a42478d"
|
||||
integrity sha1-TzFS4JVA/eKMdvRLGbvNHVpCR40=
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.13"
|
||||
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
||||
|
@ -17877,6 +17882,13 @@ watchpack@^1.5.0, watchpack@^1.7.4:
|
|||
chokidar "^3.4.1"
|
||||
watchpack-chokidar2 "^2.0.0"
|
||||
|
||||
wayfarer@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/wayfarer/-/wayfarer-7.0.1.tgz#17a64d351d49f9d3d6c508155867df7658184ce3"
|
||||
integrity sha512-yf+kAlOYnJRjLxflLy+1+xEclb6222EAVvAjSY+Yz2qAIDrXeN5wLl/G302Mwv3E0KMg1HT/WDGsvSymX0U7Rw==
|
||||
dependencies:
|
||||
nanoassert "^1.1.0"
|
||||
|
||||
wcwidth@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
|
||||
|
|
Loading…
Reference in New Issue